• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Author: Joshua Brindle <jbrindle@tresys.co
2  *	   Jason Tang	  <jtang@tresys.com>
3  *	   Caleb Case	  <ccase@tresys.com>
4  *
5  * Copyright (C) 2004-2005,2009 Tresys Technology, LLC
6  *
7  *  This library is free software; you can redistribute it and/or
8  *  modify it under the terms of the GNU Lesser General Public
9  *  License as published by the Free Software Foundation; either
10  *  version 2.1 of the License, or (at your option) any later version.
11  *
12  *  This library is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  *  Lesser General Public License for more details.
16  *
17  *  You should have received a copy of the GNU Lesser General Public
18  *  License along with this library; if not, write to the Free Software
19  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20  */
21 
22 /* This file implements only the publicly-visible module functions to libsemanage. */
23 
24 #include "direct_api.h"
25 #include "modules.h"
26 #include "semanage_conf.h"
27 #include "semanage_store.h"
28 
29 #include <stdarg.h>
30 #include <assert.h>
31 #include <stdlib.h>
32 #include <stdio.h>
33 #include <string.h>
34 #include <limits.h>
35 #include <fcntl.h>
36 #include <sys/types.h>
37 #include <sys/stat.h>
38 #include <sys/mman.h>
39 #include <errno.h>
40 #include <ctype.h>
41 
42 #include "handle.h"
43 #include "modules.h"
44 #include "sha256.h"
45 #include "debug.h"
46 
semanage_module_install(semanage_handle_t * sh,char * module_data,size_t data_len,const char * name,const char * ext_lang)47 int semanage_module_install(semanage_handle_t * sh,
48 			    char *module_data, size_t data_len, const char *name, const char *ext_lang)
49 {
50 	if (sh->funcs->install == NULL) {
51 		ERR(sh,
52 		    "No install function defined for this connection type.");
53 		return -1;
54 	} else if (!sh->is_connected) {
55 		ERR(sh, "Not connected.");
56 		return -1;
57 	} else if (!sh->is_in_transaction) {
58 		if (semanage_begin_transaction(sh) < 0) {
59 			return -1;
60 		}
61 	}
62 	sh->modules_modified = 1;
63 	return sh->funcs->install(sh, module_data, data_len, name, ext_lang);
64 }
65 
semanage_module_install_file(semanage_handle_t * sh,const char * module_name)66 int semanage_module_install_file(semanage_handle_t * sh,
67 				 const char *module_name) {
68 
69 	if (sh->funcs->install_file == NULL) {
70 		ERR(sh,
71 		    "No install function defined for this connection type.");
72 		return -1;
73 	} else if (!sh->is_connected) {
74 		ERR(sh, "Not connected.");
75 		return -1;
76 	} else if (!sh->is_in_transaction) {
77 		if (semanage_begin_transaction(sh) < 0) {
78 			return -1;
79 		}
80 	}
81 	sh->modules_modified = 1;
82 	return sh->funcs->install_file(sh, module_name);
83 }
84 
semanage_module_extract(semanage_handle_t * sh,semanage_module_key_t * modkey,int extract_cil,void ** mapped_data,size_t * data_len,semanage_module_info_t ** modinfo)85 int semanage_module_extract(semanage_handle_t * sh,
86 				 semanage_module_key_t *modkey,
87 				 int extract_cil,
88 				 void **mapped_data,
89 				 size_t *data_len,
90 				 semanage_module_info_t **modinfo) {
91 	if (sh->funcs->extract == NULL) {
92 		ERR(sh,
93 		    "No get function defined for this connection type.");
94 		return -1;
95 	} else if (!sh->is_connected) {
96 		ERR(sh, "Not connected.");
97 		return -1;
98 	}
99 	return sh->funcs->extract(sh, modkey, extract_cil, mapped_data, data_len, modinfo);
100 }
101 
102 /* Legacy function that remains to preserve ABI
103  * compatibility. Please use semanage_module_install_file instead.
104  */
semanage_module_upgrade_file(semanage_handle_t * sh,const char * module_name)105 int semanage_module_upgrade_file(semanage_handle_t * sh,
106 				 const char *module_name)
107 {
108 	return semanage_module_install_file(sh, module_name);
109 }
110 
semanage_module_remove(semanage_handle_t * sh,char * module_name)111 int semanage_module_remove(semanage_handle_t * sh, char *module_name)
112 {
113 	if (sh->funcs->remove == NULL) {
114 		ERR(sh, "No remove function defined for this connection type.");
115 		return -1;
116 	} else if (!sh->is_connected) {
117 		ERR(sh, "Not connected.");
118 		return -1;
119 	} else if (!sh->is_in_transaction) {
120 		if (semanage_begin_transaction(sh) < 0) {
121 			return -1;
122 		}
123 	}
124 	sh->modules_modified = 1;
125 	return sh->funcs->remove(sh, module_name);
126 }
127 
semanage_module_list(semanage_handle_t * sh,semanage_module_info_t ** modinfo,int * num_modules)128 int semanage_module_list(semanage_handle_t * sh,
129 			 semanage_module_info_t ** modinfo, int *num_modules)
130 {
131 	if (sh->funcs->list == NULL) {
132 		ERR(sh, "No list function defined for this connection type.");
133 		return -1;
134 	} else if (!sh->is_connected) {
135 		ERR(sh, "Not connected.");
136 		return -1;
137 	}
138 	return sh->funcs->list(sh, modinfo, num_modules);
139 }
140 
semanage_module_info_datum_destroy(semanage_module_info_t * modinfo)141 void semanage_module_info_datum_destroy(semanage_module_info_t * modinfo)
142 {
143 	if (modinfo != NULL) {
144 		modinfo->priority = 0;
145 
146 		free(modinfo->name);
147 		modinfo->name = NULL;
148 
149 		free(modinfo->lang_ext);
150 		modinfo->lang_ext = NULL;
151 
152 		modinfo->enabled = -1;
153 	}
154 }
155 
156 
semanage_module_list_nth(semanage_module_info_t * list,int n)157 semanage_module_info_t *semanage_module_list_nth(semanage_module_info_t * list,
158 						 int n)
159 {
160 	return list + n;
161 }
162 
163 
semanage_module_get_name(semanage_module_info_t * modinfo)164 const char *semanage_module_get_name(semanage_module_info_t * modinfo)
165 {
166 	return modinfo->name;
167 }
168 
169 
170 /* Legacy function that remains to preserve ABI
171  * compatibility.
172  */
173 extern const char *semanage_module_get_version(semanage_module_info_t *);
semanage_module_get_version(semanage_module_info_t * modinfo)174 const char *semanage_module_get_version(semanage_module_info_t * modinfo
175 				__attribute__ ((unused)))
176 {
177 	return "";
178 }
179 
semanage_module_info_create(semanage_handle_t * sh,semanage_module_info_t ** modinfo)180 int semanage_module_info_create(semanage_handle_t *sh,
181 				semanage_module_info_t **modinfo)
182 {
183 	assert(sh);
184 	assert(modinfo);
185 
186 	*modinfo = malloc(sizeof(semanage_module_info_t));
187 	if (*modinfo == NULL) return -1;
188 
189 	return semanage_module_info_init(sh, *modinfo);
190 }
191 
192 
semanage_module_info_destroy(semanage_handle_t * sh,semanage_module_info_t * modinfo)193 int semanage_module_info_destroy(semanage_handle_t *sh,
194 				 semanage_module_info_t *modinfo)
195 {
196 	assert(sh);
197 
198 	if (!modinfo) {
199 		return 0;
200 	}
201 
202 	free(modinfo->name);
203 	free(modinfo->lang_ext);
204 
205 	return semanage_module_info_init(sh, modinfo);
206 }
207 
208 
semanage_module_info_init(semanage_handle_t * sh,semanage_module_info_t * modinfo)209 int semanage_module_info_init(semanage_handle_t *sh,
210 			      semanage_module_info_t *modinfo)
211 {
212 	assert(sh);
213 	assert(modinfo);
214 
215 	modinfo->priority = 0;
216 	modinfo->name = NULL;
217 	modinfo->lang_ext = NULL;
218 	modinfo->enabled = -1;
219 
220 	return 0;
221 }
222 
semanage_module_info_clone(semanage_handle_t * sh,const semanage_module_info_t * source,semanage_module_info_t * target)223 int semanage_module_info_clone(semanage_handle_t *sh,
224 			       const semanage_module_info_t *source,
225 			       semanage_module_info_t *target)
226 {
227 	assert(sh);
228 	assert(source);
229 	assert(target);
230 
231 	int status = 0;
232 	int ret = 0;
233 
234 	ret = semanage_module_info_destroy(sh, target);
235 	if (ret != 0) {
236 		status = -1;
237 		goto cleanup;
238 	}
239 
240 	ret = semanage_module_info_set_priority(sh, target, source->priority);
241 	if (ret != 0) {
242 		status = -1;
243 		goto cleanup;
244 	}
245 
246 	ret = semanage_module_info_set_name(sh, target, source->name);
247 	if (ret != 0) {
248 		status = -1;
249 		goto cleanup;
250 	}
251 
252 	ret = semanage_module_info_set_lang_ext(sh, target, source->lang_ext);
253 	if (ret != 0) {
254 		status = -1;
255 		goto cleanup;
256 	}
257 
258 	ret = semanage_module_info_set_enabled(sh, target, source->enabled);
259 	if (ret != 0) {
260 		status = -1;
261 		goto cleanup;
262 	}
263 
264 cleanup:
265 	if (status != 0) semanage_module_info_destroy(sh, target);
266 	return status;
267 }
268 
semanage_module_info_get_priority(semanage_handle_t * sh,semanage_module_info_t * modinfo,uint16_t * priority)269 int semanage_module_info_get_priority(semanage_handle_t *sh,
270 				      semanage_module_info_t *modinfo,
271 				      uint16_t *priority)
272 {
273 	assert(sh);
274 	assert(modinfo);
275 	assert(priority);
276 
277 	*priority = modinfo->priority;
278 
279 	return 0;
280 }
281 
282 
semanage_module_info_get_name(semanage_handle_t * sh,semanage_module_info_t * modinfo,const char ** name)283 int semanage_module_info_get_name(semanage_handle_t *sh,
284 				  semanage_module_info_t *modinfo,
285 				  const char **name)
286 {
287 	assert(sh);
288 	assert(modinfo);
289 	assert(name);
290 
291 	*name = modinfo->name;
292 
293 	return 0;
294 }
295 
296 
semanage_module_info_get_lang_ext(semanage_handle_t * sh,semanage_module_info_t * modinfo,const char ** lang_ext)297 int semanage_module_info_get_lang_ext(semanage_handle_t *sh,
298 				      semanage_module_info_t *modinfo,
299 				      const char **lang_ext)
300 {
301 	assert(sh);
302 	assert(modinfo);
303 	assert(lang_ext);
304 
305 	*lang_ext = modinfo->lang_ext;
306 
307 	return 0;
308 }
309 
310 
semanage_module_info_get_enabled(semanage_handle_t * sh,semanage_module_info_t * modinfo,int * enabled)311 int semanage_module_info_get_enabled(semanage_handle_t *sh,
312 				     semanage_module_info_t *modinfo,
313 				     int *enabled)
314 {
315 	assert(sh);
316 	assert(modinfo);
317 	assert(enabled);
318 
319 	*enabled = modinfo->enabled;
320 
321 	return 0;
322 }
323 
324 
semanage_module_info_set_priority(semanage_handle_t * sh,semanage_module_info_t * modinfo,uint16_t priority)325 int semanage_module_info_set_priority(semanage_handle_t *sh,
326 				      semanage_module_info_t *modinfo,
327 				      uint16_t priority)
328 {
329 	assert(sh);
330 	assert(modinfo);
331 
332 	/* Verify priority */
333 	if (semanage_module_validate_priority(priority) < 0) {
334 		errno = 0;
335 		ERR(sh, "Priority %d is invalid.", priority);
336 		return -1;
337 	}
338 
339 	modinfo->priority = priority;
340 
341 	return 0;
342 }
343 
344 
semanage_module_info_set_name(semanage_handle_t * sh,semanage_module_info_t * modinfo,const char * name)345 int semanage_module_info_set_name(semanage_handle_t *sh,
346 				  semanage_module_info_t *modinfo,
347 				  const char *name)
348 {
349 	assert(sh);
350 	assert(modinfo);
351 	assert(name);
352 
353 	char * tmp;
354 
355 	/* Verify name */
356 	if (semanage_module_validate_name(name) < 0) {
357 		errno = 0;
358 		ERR(sh, "Name %s is invalid.", name);
359 		return -1;
360 	}
361 
362 	tmp = strdup(name);
363 	if (!tmp) {
364 		ERR(sh, "No memory available for strdup");
365 		return -1;
366 	}
367 
368 	free(modinfo->name);
369 	modinfo->name = tmp;
370 
371 	return 0;
372 }
373 
374 
semanage_module_info_set_lang_ext(semanage_handle_t * sh,semanage_module_info_t * modinfo,const char * lang_ext)375 int semanage_module_info_set_lang_ext(semanage_handle_t *sh,
376 				      semanage_module_info_t *modinfo,
377 				      const char *lang_ext)
378 {
379 	assert(sh);
380 	assert(modinfo);
381 	assert(lang_ext);
382 
383 	char * tmp;
384 
385 	/* Verify extension */
386 	if (semanage_module_validate_lang_ext(lang_ext) < 0) {
387 		errno = 0;
388 		ERR(sh, "Language extensions %s is invalid.", lang_ext);
389 		return -1;
390 	}
391 
392 	tmp = strdup(lang_ext);
393 	if (!tmp) {
394 		ERR(sh, "No memory available for strdup");
395 		return -1;
396 	}
397 
398 	free(modinfo->lang_ext);
399 	modinfo->lang_ext = tmp;
400 
401 	return 0;
402 }
403 
404 
semanage_module_info_set_enabled(semanage_handle_t * sh,semanage_module_info_t * modinfo,int enabled)405 int semanage_module_info_set_enabled(semanage_handle_t *sh,
406 				     semanage_module_info_t *modinfo,
407 				     int enabled)
408 {
409 	assert(sh);
410 	assert(modinfo);
411 
412 	/* Verify enabled */
413 	if (semanage_module_validate_enabled(enabled) < 0) {
414 		errno = 0;
415 		ERR(sh, "Enabled status %d is invalid.", enabled);
416 		return -1;
417 	}
418 
419 	modinfo->enabled = enabled;
420 
421 	return 0;
422 }
423 
424 
semanage_module_get_path(semanage_handle_t * sh,const semanage_module_info_t * modinfo,enum semanage_module_path_type type,char * path,size_t len)425 int semanage_module_get_path(semanage_handle_t *sh,
426 			     const semanage_module_info_t *modinfo,
427 			     enum semanage_module_path_type type,
428 			     char *path,
429 			     size_t len)
430 {
431 	assert(sh);
432 	assert(modinfo);
433 	assert(path);
434 
435 	int status = 0;
436 	int ret = 0;
437 
438 	const char *modules_path = NULL;
439 	const char *file = NULL;
440 
441 	modules_path = sh->is_in_transaction ?
442 		semanage_path(SEMANAGE_TMP, SEMANAGE_MODULES):
443 		semanage_path(SEMANAGE_ACTIVE, SEMANAGE_MODULES);
444 
445 	switch (type) {
446 		case SEMANAGE_MODULE_PATH_PRIORITY:
447 			/* verify priority */
448 			ret = semanage_module_validate_priority(modinfo->priority);
449 			if (ret < 0) {
450 				errno = 0;
451 				ERR(sh,
452 				    "Priority %d is invalid.",
453 				    modinfo->priority);
454 				status = ret;
455 				goto cleanup;
456 			}
457 
458 			ret = snprintf(path,
459 				       len,
460 				       "%s/%03u",
461 				       modules_path,
462 				       modinfo->priority);
463 			if (ret < 0 || (size_t)ret >= len) {
464 				ERR(sh, "Unable to compose priority path.");
465 				status = -1;
466 				goto cleanup;
467 			}
468 			break;
469 		case SEMANAGE_MODULE_PATH_NAME:
470 			/* verify priority and name */
471 			ret = semanage_module_validate_priority(modinfo->priority);
472 			if (ret < 0) {
473 				errno = 0;
474 				ERR(sh,
475 				    "Priority %d is invalid.",
476 				    modinfo->priority);
477 				status = -1;
478 				goto cleanup;
479 			}
480 
481 			ret = semanage_module_validate_name(modinfo->name);
482 			if (ret < 0) {
483 				errno = 0;
484 				ERR(sh, "Name %s is invalid.", modinfo->name);
485 				status = -1;
486 				goto cleanup;
487 			}
488 
489 			ret = snprintf(path,
490 				       len,
491 				       "%s/%03u/%s",
492 				       modules_path,
493 				       modinfo->priority,
494 				       modinfo->name);
495 			if (ret < 0 || (size_t)ret >= len) {
496 				ERR(sh, "Unable to compose name path.");
497 				status = -1;
498 				goto cleanup;
499 			}
500 			break;
501 		case SEMANAGE_MODULE_PATH_HLL:
502 			if (file == NULL) file = "hll";
503 			/* FALLTHRU */
504 		case SEMANAGE_MODULE_PATH_CIL:
505 			if (file == NULL) file = "cil";
506 			/* FALLTHRU */
507 		case SEMANAGE_MODULE_PATH_LANG_EXT:
508 			if (file == NULL) file = "lang_ext";
509 
510 			/* verify priority and name */
511 			ret = semanage_module_validate_priority(modinfo->priority);
512 			if (ret < 0) {
513 				errno = 0;
514 				ERR(sh,
515 				    "Priority %d is invalid.",
516 				    modinfo->priority);
517 				status = -1;
518 				goto cleanup;
519 			}
520 
521 			ret = semanage_module_validate_name(modinfo->name);
522 			if (ret < 0) {
523 				errno = 0;
524 				ERR(sh, "Name %s is invalid.", modinfo->name);
525 				status = -1;
526 				goto cleanup;
527 			}
528 
529 			ret = snprintf(path,
530 				       len,
531 				       "%s/%03u/%s/%s",
532 				       modules_path,
533 				       modinfo->priority,
534 				       modinfo->name,
535 				       file);
536 			if (ret < 0 || (size_t)ret >= len) {
537 				ERR(sh,
538 				    "Unable to compose path for %s file.",
539 				    file);
540 				status = -1;
541 				goto cleanup;
542 			}
543 			break;
544 		case SEMANAGE_MODULE_PATH_DISABLED:
545 			/* verify name */
546 			ret = semanage_module_validate_name(modinfo->name);
547 			if (ret < 0) {
548 				errno = 0;
549 				ERR(sh, "Name %s is invalid.", modinfo->name);
550 				status = -1;
551 				goto cleanup;
552 			}
553 
554 			ret = snprintf(path,
555 				       len,
556 				       "%s/disabled/%s",
557 				       modules_path,
558 				       modinfo->name);
559 			if (ret < 0 || (size_t)ret >= len) {
560 				ERR(sh,
561 				    "Unable to compose disabled status path.");
562 				status = -1;
563 				goto cleanup;
564 			}
565 			break;
566 		default:
567 			ERR(sh, "Invalid module path type %d.", type);
568 			status = -1;
569 			goto cleanup;
570 	}
571 
572 cleanup:
573 	return status;
574 }
575 
semanage_module_key_create(semanage_handle_t * sh,semanage_module_key_t ** modkey)576 int semanage_module_key_create(semanage_handle_t *sh,
577 			       semanage_module_key_t **modkey)
578 {
579 	assert(sh);
580 	assert(modkey);
581 
582 	*modkey = malloc(sizeof(semanage_module_key_t));
583 	if (*modkey == NULL) return -1;
584 
585 	return semanage_module_key_init(sh, *modkey);
586 }
587 
588 
semanage_module_key_destroy(semanage_handle_t * sh,semanage_module_key_t * modkey)589 int semanage_module_key_destroy(semanage_handle_t *sh,
590 				semanage_module_key_t *modkey)
591 {
592 	assert(sh);
593 
594 	if (!modkey) {
595 		return 0;
596 	}
597 
598 	free(modkey->name);
599 
600 	return semanage_module_key_init(sh, modkey);
601 }
602 
603 
semanage_module_key_init(semanage_handle_t * sh,semanage_module_key_t * modkey)604 int semanage_module_key_init(semanage_handle_t *sh,
605 			     semanage_module_key_t *modkey)
606 {
607 	assert(sh);
608 	assert(modkey);
609 
610 	modkey->name = NULL;
611 	modkey->priority = 0;
612 
613 	return 0;
614 }
615 
semanage_module_key_get_name(semanage_handle_t * sh,semanage_module_key_t * modkey,const char ** name)616 int semanage_module_key_get_name(semanage_handle_t *sh,
617 				 semanage_module_key_t *modkey,
618 				 const char **name)
619 {
620 	assert(sh);
621 	assert(modkey);
622 	assert(name);
623 
624 	*name = modkey->name;
625 
626 	return 0;
627 }
628 
629 
semanage_module_key_get_priority(semanage_handle_t * sh,semanage_module_key_t * modkey,uint16_t * priority)630 int semanage_module_key_get_priority(semanage_handle_t *sh,
631 				     semanage_module_key_t *modkey,
632 				     uint16_t *priority)
633 {
634 	assert(sh);
635 	assert(modkey);
636 	assert(priority);
637 
638 	*priority = modkey->priority;
639 
640 	return 0;
641 }
642 
643 
semanage_module_key_set_name(semanage_handle_t * sh,semanage_module_key_t * modkey,const char * name)644 int semanage_module_key_set_name(semanage_handle_t *sh,
645 				 semanage_module_key_t *modkey,
646 				 const char *name)
647 {
648 	assert(sh);
649 	assert(modkey);
650 	assert(name);
651 
652 	int status = 0;
653 	char *tmp = NULL;
654 
655 	if (semanage_module_validate_name(name) < 0) {
656 		errno = 0;
657 		ERR(sh, "Name %s is invalid.", name);
658 		return -1;
659 	}
660 
661 	tmp = strdup(name);
662 	if (tmp == NULL) {
663 		ERR(sh, "No memory available for strdup");
664 		status = -1;
665 		goto cleanup;
666 	}
667 
668 	free(modkey->name);
669 	modkey->name = tmp;
670 
671 cleanup:
672 	return status;
673 }
674 
675 
semanage_module_key_set_priority(semanage_handle_t * sh,semanage_module_key_t * modkey,uint16_t priority)676 int semanage_module_key_set_priority(semanage_handle_t *sh,
677 				     semanage_module_key_t *modkey,
678 				     uint16_t priority)
679 {
680 	assert(sh);
681 	assert(modkey);
682 
683 	if (semanage_module_validate_priority(priority) < 0) {
684 		errno = 0;
685 		ERR(sh, "Priority %d is invalid.", priority);
686 		return -1;
687 	}
688 
689 	modkey->priority = priority;
690 
691 	return 0;
692 }
693 
694 
semanage_module_get_enabled(semanage_handle_t * sh,const semanage_module_key_t * modkey,int * enabled)695 int semanage_module_get_enabled(semanage_handle_t *sh,
696 				const semanage_module_key_t *modkey,
697 				int *enabled)
698 {
699 	assert(sh);
700 	assert(modkey);
701 	assert(enabled);
702 
703 	if (sh->funcs->get_enabled == NULL) {
704 		ERR(sh,
705 		    "No get_enabled function defined for this connection type.");
706 		return -1;
707 	} else if (!sh->is_connected) {
708 		ERR(sh, "Not connected.");
709 		return -1;
710 	}
711 
712 	return sh->funcs->get_enabled(sh, modkey, enabled);
713 }
714 
semanage_module_set_enabled(semanage_handle_t * sh,const semanage_module_key_t * modkey,int enabled)715 int semanage_module_set_enabled(semanage_handle_t *sh,
716 				const semanage_module_key_t *modkey,
717 				int enabled)
718 {
719 	assert(sh);
720 	assert(modkey);
721 
722 	if (sh->funcs->set_enabled == NULL) {
723 		ERR(sh,
724 		    "No set_enabled function defined for this connection type.");
725 		return -1;
726 	} else if (!sh->is_connected) {
727 		ERR(sh, "Not connected.");
728 		return -1;
729 	} else if (!sh->is_in_transaction) {
730 		if (semanage_begin_transaction(sh) < 0) {
731 			return -1;
732 		}
733 	}
734 
735 	sh->modules_modified = 1;
736 	return sh->funcs->set_enabled(sh, modkey, enabled);
737 }
738 
739 
740 /* Converts a string to a priority
741  *
742  * returns -1 if str is not a valid priority.
743  * returns 0 and sets priority if str is a valid priority
744  */
semanage_string_to_priority(const char * str,uint16_t * priority)745 int semanage_string_to_priority(const char *str, uint16_t *priority)
746 {
747 	unsigned long val;
748 	char *endptr = NULL;
749 	int status = -1;
750 
751 	if (str == NULL || priority == NULL) {
752 		goto exit;
753 	}
754 
755 	errno = 0;
756 
757 	val = strtoul(str, &endptr, 10);
758 
759 	if (errno != 0 || endptr == str || *endptr != '\0' || val > UINT16_MAX) {
760 		goto exit;
761 	}
762 
763 	if (semanage_module_validate_priority((uint16_t)val) < 0) {
764 		goto exit;
765 	}
766 
767 	*priority = val;
768 	status = 0;
769 
770 exit:
771 	return status;
772 }
773 
774 /* Validates a module info struct.
775  *
776  * Returns -1 if module is invalid, 0 otherwise.
777  */
semanage_module_info_validate(const semanage_module_info_t * modinfo)778 int semanage_module_info_validate(const semanage_module_info_t *modinfo)
779 {
780 	if (semanage_module_validate_priority(modinfo->priority) != 0 ||
781 	    semanage_module_validate_name(modinfo->name) != 0 ||
782 	    semanage_module_validate_lang_ext(modinfo->lang_ext) != 0 ||
783 	    semanage_module_validate_enabled(modinfo->enabled) != 0) {
784 		return -1;
785 	}
786 	return 0;
787 }
788 
789 #define PRIORITY_MIN 1
790 #define PRIORITY_MAX 999
791 
792 /* Validates priority.
793  *
794  * returns -1 if priority is not in the valid range, returns 0 otherwise
795  */
semanage_module_validate_priority(uint16_t priority)796 int semanage_module_validate_priority(uint16_t priority)
797 {
798 	if (priority >= PRIORITY_MIN && priority <= PRIORITY_MAX) {
799 		return 0;
800 	}
801 
802 	return -1;
803 }
804 
805 /* Validates module name.
806  *
807  * A module name must match one of the following regular expressions
808  * to be considered valid:
809  *
810  * ^[a-zA-Z](\.?[a-zA-Z0-9_-])*$
811  *
812  * returns -1 if name is not valid, returns 0 otherwise
813  */
semanage_module_validate_name(const char * name)814 int semanage_module_validate_name(const char * name)
815 {
816 	int status = 0;
817 
818 	if (name == NULL) {
819 		status = -1;
820 		goto exit;
821 	}
822 
823 	if (!isalpha(*name)) {
824 		status = -1;
825 		goto exit;
826 	}
827 
828 #define ISVALIDCHAR(c) (isalnum(c) || c == '_' || c == '-')
829 
830 	for (name++; *name; name++) {
831 		if (ISVALIDCHAR(*name)) {
832 			continue;
833 		}
834 		if (*name == '.' && name++ && ISVALIDCHAR(*name)) {
835 			continue;
836 		}
837 		status = -1;
838 		goto exit;
839 	}
840 
841 #undef ISVALIDCHAR
842 
843 exit:
844 	return status;
845 }
846 
847 /* Validates module enabled status.
848  *
849  * Valid enabled values are 1, 0, and -1.
850  *
851  * returns 0 if enabled is a valid value, returns -1 otherwise.
852  */
semanage_module_validate_enabled(int enabled)853 int semanage_module_validate_enabled(int enabled)
854 {
855 	if (enabled == 1 || enabled == 0 || enabled == -1) {
856 		return 0;
857 	}
858 
859 	return -1;
860 }
861 
862 /* Validate extension.
863  *
864  * An extension must match the following regular expression to be
865  * considered valid:
866  *
867  * ^[a-zA-Z0-9][a-zA-Z0-9_-]*$
868  *
869  * returns 0 if ext is a valid value, returns -1 otherwise.
870  */
semanage_module_validate_lang_ext(const char * ext)871 int semanage_module_validate_lang_ext(const char *ext)
872 {
873 	int status = 0;
874 
875 	if (ext == NULL) {
876 		status = -1;
877 		goto exit;
878 	}
879 
880 	if (!isalnum(*ext)) {
881 		status = -1;
882 		goto exit;
883 	}
884 
885 #define ISVALIDCHAR(c) (isalnum(c) || c == '_' || c == '-')
886 
887 	for (ext++; *ext; ext++) {
888 		if (ISVALIDCHAR(*ext)) {
889 			continue;
890 		}
891 		status = -1;
892 		goto exit;
893 	}
894 
895 #undef ISVALIDCHAR
896 
897 exit:
898 	return status;
899 }
900 
semanage_module_get_module_info(semanage_handle_t * sh,const semanage_module_key_t * modkey,semanage_module_info_t ** modinfo)901 int semanage_module_get_module_info(semanage_handle_t *sh,
902 				    const semanage_module_key_t *modkey,
903 				    semanage_module_info_t **modinfo)
904 {
905 	assert(sh);
906 	assert(modkey);
907 	assert(modinfo);
908 
909 	if (sh->funcs->get_module_info == NULL) {
910 		ERR(sh,
911 		    "No get module info function defined for this connection type.");
912 		return -1;
913 	} else if (!sh->is_connected) {
914 		ERR(sh, "Not connected.");
915 		return -1;
916 	}
917 
918 	return sh->funcs->get_module_info(sh, modkey, modinfo);
919 }
920 
semanage_module_list_all(semanage_handle_t * sh,semanage_module_info_t ** modinfos,int * modinfos_len)921 int semanage_module_list_all(semanage_handle_t *sh,
922 			     semanage_module_info_t **modinfos,
923 			     int *modinfos_len)
924 {
925 	assert(sh);
926 	assert(modinfos);
927 	assert(modinfos_len);
928 
929 	if (sh->funcs->list_all == NULL) {
930 		ERR(sh,
931 		    "No list all function defined for this connection type.");
932 		return -1;
933 	} else if (!sh->is_connected) {
934 		ERR(sh, "Not connected.");
935 		return -1;
936 	}
937 
938 	return sh->funcs->list_all(sh, modinfos, modinfos_len);
939 }
940 
semanage_module_install_info(semanage_handle_t * sh,const semanage_module_info_t * modinfo,char * data,size_t data_len)941 int semanage_module_install_info(semanage_handle_t *sh,
942 				 const semanage_module_info_t *modinfo,
943 				 char *data,
944 				 size_t data_len)
945 {
946 	if (sh->funcs->install_info == NULL) {
947 		ERR(sh,
948 		    "No install info function defined for this connection type.");
949 		return -1;
950 	} else if (!sh->is_connected) {
951 		ERR(sh, "Not connected.");
952 		return -1;
953 	} else if (!sh->is_in_transaction) {
954 		if (semanage_begin_transaction(sh) < 0) {
955 			return -1;
956 		}
957 	}
958 	sh->modules_modified = 1;
959 	return sh->funcs->install_info(sh, modinfo, data, data_len);
960 }
961 
semanage_module_remove_key(semanage_handle_t * sh,const semanage_module_key_t * modkey)962 int semanage_module_remove_key(semanage_handle_t *sh,
963 			       const semanage_module_key_t *modkey)
964 {
965 	if (sh->funcs->remove_key == NULL) {
966 		ERR(sh,
967 		    "No remove key function defined for this connection type.");
968 		return -1;
969 	} else if (!sh->is_connected) {
970 		ERR(sh, "Not connected.");
971 		return -1;
972 	} else if (!sh->is_in_transaction) {
973 		if (semanage_begin_transaction(sh) < 0) {
974 			return -1;
975 		}
976 	}
977 	sh->modules_modified = 1;
978 	return sh->funcs->remove_key(sh, modkey);
979 }
980 
981 static const char CHECKSUM_TYPE[] = "sha256";
982 const size_t CHECKSUM_CONTENT_SIZE = sizeof(CHECKSUM_TYPE) + 1 + 2 * SHA256_HASH_SIZE;
983 
semanage_hash_to_checksum_string(const uint8_t * hash,char * checksum)984 void semanage_hash_to_checksum_string(const uint8_t *hash, char *checksum)
985 {
986 	size_t i;
987 
988 	checksum += sprintf(checksum, "%s:", CHECKSUM_TYPE);
989 	for (i = 0; i < SHA256_HASH_SIZE; i++) {
990 		checksum += sprintf(checksum, "%02x", (unsigned)hash[i]);
991 	}
992 }
993 
semanage_module_compute_checksum(semanage_handle_t * sh,semanage_module_key_t * modkey,int cil,char ** checksum,size_t * checksum_len)994 int semanage_module_compute_checksum(semanage_handle_t *sh,
995 				     semanage_module_key_t *modkey,
996 				     int cil, char **checksum,
997 				     size_t *checksum_len)
998 {
999 	semanage_module_info_t *extract_info = NULL;
1000 	Sha256Context context;
1001 	SHA256_HASH sha256_hash;
1002 	char *checksum_str;
1003 	void *data;
1004 	size_t data_len = 0;
1005 	int result;
1006 
1007 	if (!checksum_len)
1008 		return -1;
1009 
1010 	if (!checksum) {
1011 		*checksum_len = CHECKSUM_CONTENT_SIZE;
1012 		return 0;
1013 	}
1014 
1015 	result = semanage_module_extract(sh, modkey, cil, &data, &data_len, &extract_info);
1016 	if (result != 0)
1017 		return -1;
1018 
1019 	semanage_module_info_destroy(sh, extract_info);
1020 	free(extract_info);
1021 
1022 	Sha256Initialise(&context);
1023 	Sha256Update(&context, data, data_len);
1024 	Sha256Finalise(&context, &sha256_hash);
1025 
1026 	munmap(data, data_len);
1027 
1028 	checksum_str = malloc(CHECKSUM_CONTENT_SIZE + 1 /* '\0' */);
1029 	if (!checksum_str)
1030 		return -1;
1031 
1032 	semanage_hash_to_checksum_string(sha256_hash.bytes, checksum_str);
1033 
1034 	*checksum = checksum_str;
1035 	*checksum_len = CHECKSUM_CONTENT_SIZE;
1036 	return 0;
1037 }
1038