blob: 4d4d60a468bbb1d9130d951df09e3b686a15670d [file] [log] [blame]
Joshua Brindle13cd4c82008-08-19 15:30:36 -04001/* Author: Joshua Brindle <jbrindle@tresys.co
2 * Jason Tang <jtang@tresys.com>
Caleb Cased220f492009-12-23 18:25:54 -05003 * Caleb Case <ccase@tresys.com>
Joshua Brindle13cd4c82008-08-19 15:30:36 -04004 *
Caleb Cased220f492009-12-23 18:25:54 -05005 * Copyright (C) 2004-2005,2009 Tresys Technology, LLC
Joshua Brindle13cd4c82008-08-19 15:30:36 -04006 *
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 "semanage_conf.h"
26#include "semanage_store.h"
27
28#include <stdarg.h>
29#include <assert.h>
30#include <stdlib.h>
31#include <stdio.h>
Caleb Cased220f492009-12-23 18:25:54 -050032#include <string.h>
33#include <limits.h>
34#include <fcntl.h>
35#include <sys/types.h>
36#include <sys/stat.h>
37#include <errno.h>
38#include <ctype.h>
Joshua Brindle13cd4c82008-08-19 15:30:36 -040039
40#include "handle.h"
41#include "modules.h"
42#include "debug.h"
43
Steve Lawrence9fbc6d12014-06-13 13:20:26 -040044asm(".symver semanage_module_get_enabled_1_1,semanage_module_get_enabled@@LIBSEMANAGE_1.1");
45asm(".symver semanage_module_get_enabled_1_0,semanage_module_get_enabled@LIBSEMANAGE_1.0");
Steve Lawrenced5bcc222011-10-14 15:29:29 -040046asm(".symver semanage_module_install_pp,semanage_module_install@LIBSEMANAGE_1.0");
47asm(".symver semanage_module_install_hll,semanage_module_install@@LIBSEMANAGE_1.1");
Steve Lawrence9fbc6d12014-06-13 13:20:26 -040048
Steve Lawrenced5bcc222011-10-14 15:29:29 -040049/* Takes a module stored in 'module_data' and parses its headers.
50 * Sets reference variables 'module_name' to module's name and
51 * 'version' to module's version. The caller is responsible for
52 * free()ing 'module_name' and 'version'; they will be
53 * set to NULL upon entering this function. Returns 0 on success, -1
54 * if out of memory, or -2 if data did not represent a module.
55 */
56static int parse_module_headers(semanage_handle_t * sh, char *module_data,
57 size_t data_len, char **module_name, char **version)
58{
59 struct sepol_policy_file *pf;
60 int file_type;
61 *version = NULL;
62
63 if (sepol_policy_file_create(&pf)) {
64 ERR(sh, "Out of memory!");
65 return -1;
66 }
67 sepol_policy_file_set_mem(pf, module_data, data_len);
68 sepol_policy_file_set_handle(pf, sh->sepolh);
69 if (module_data == NULL ||
70 data_len == 0 ||
71 sepol_module_package_info(pf, &file_type, module_name, version) == -1) {
72 sepol_policy_file_free(pf);
73 ERR(sh, "Could not parse module data.");
74 return -2;
75 }
76 sepol_policy_file_free(pf);
77 if (file_type != SEPOL_POLICY_MOD) {
78 ERR(sh, "Data did not represent a pp module. Please upgrade to the latest version of libsemanage to support hll modules.");
79 return -2;
80 }
81
82 return 0;
83}
84
85/* This function is used to preserve ABI compatibility with
86 * versions of semodule using LIBSEMANAGE_1.0
87 */
88int semanage_module_install_pp(semanage_handle_t * sh,
Joshua Brindle13cd4c82008-08-19 15:30:36 -040089 char *module_data, size_t data_len)
90{
Steve Lawrenced5bcc222011-10-14 15:29:29 -040091 char *name = NULL;
92 char *version = NULL;
93 int status;
94
95 if ((status = parse_module_headers(sh, module_data, data_len, &name, &version)) != 0) {
96 goto cleanup;
97 }
98
99 status = semanage_module_install_hll(sh, module_data, data_len, name, "pp");
100
101cleanup:
102 free(name);
103 free(version);
104 return status;
105}
106
107int semanage_module_install_hll(semanage_handle_t * sh,
108 char *module_data, size_t data_len, char *name, char *ext_lang)
109{
Joshua Brindle13cd4c82008-08-19 15:30:36 -0400110 if (sh->funcs->install == NULL) {
111 ERR(sh,
112 "No install function defined for this connection type.");
113 return -1;
114 } else if (!sh->is_connected) {
115 ERR(sh, "Not connected.");
116 return -1;
117 } else if (!sh->is_in_transaction) {
118 if (semanage_begin_transaction(sh) < 0) {
119 return -1;
120 }
121 }
122 sh->modules_modified = 1;
Steve Lawrenced5bcc222011-10-14 15:29:29 -0400123 return sh->funcs->install(sh, module_data, data_len, name, ext_lang);
Joshua Brindle13cd4c82008-08-19 15:30:36 -0400124}
125
Joshua Brindledf77db42009-01-05 05:37:06 -0500126int semanage_module_install_file(semanage_handle_t * sh,
127 const char *module_name) {
128
129 if (sh->funcs->install_file == NULL) {
130 ERR(sh,
131 "No install function defined for this connection type.");
132 return -1;
133 } else if (!sh->is_connected) {
134 ERR(sh, "Not connected.");
135 return -1;
136 } else if (!sh->is_in_transaction) {
137 if (semanage_begin_transaction(sh) < 0) {
138 return -1;
139 }
140 }
141 sh->modules_modified = 1;
142 return sh->funcs->install_file(sh, module_name);
143}
144
Steve Lawrenced5bcc222011-10-14 15:29:29 -0400145/* Legacy function that remains to preserve ABI
146 * compatibility. Please use semanage_module_install instead.
147 */
Joshua Brindle13cd4c82008-08-19 15:30:36 -0400148int semanage_module_upgrade(semanage_handle_t * sh,
149 char *module_data, size_t data_len)
150{
Steve Lawrenced5bcc222011-10-14 15:29:29 -0400151 return semanage_module_install_pp(sh, module_data, data_len);
Daniel J Walshc282c402009-09-11 14:40:48 -0400152
Joshua Brindle13cd4c82008-08-19 15:30:36 -0400153}
154
Steve Lawrenced5bcc222011-10-14 15:29:29 -0400155/* Legacy function that remains to preserve ABI
156 * compatibility. Please use semanage_module_install_file instead.
157 */
Joshua Brindledf77db42009-01-05 05:37:06 -0500158int semanage_module_upgrade_file(semanage_handle_t * sh,
Steve Lawrenced5bcc222011-10-14 15:29:29 -0400159 const char *module_name)
160{
161 return semanage_module_install_file(sh, module_name);
Joshua Brindledf77db42009-01-05 05:37:06 -0500162}
163
Steve Lawrenced5bcc222011-10-14 15:29:29 -0400164/* Legacy function that remains to preserve ABI
165 * compatibility. Please use semanage_module_install instead.
166 */
Joshua Brindle13cd4c82008-08-19 15:30:36 -0400167int semanage_module_install_base(semanage_handle_t * sh,
168 char *module_data, size_t data_len)
169{
Steve Lawrenced5bcc222011-10-14 15:29:29 -0400170 return semanage_module_install_pp(sh, module_data, data_len);
Joshua Brindle13cd4c82008-08-19 15:30:36 -0400171}
172
Steve Lawrenced5bcc222011-10-14 15:29:29 -0400173/* Legacy function that remains to preserve ABI
174 * compatibility. Please use semanage_module_install_file instead.
175 */
Joshua Brindledf77db42009-01-05 05:37:06 -0500176int semanage_module_install_base_file(semanage_handle_t * sh,
Steve Lawrenced5bcc222011-10-14 15:29:29 -0400177 const char *module_name)
178{
179 return semanage_module_install_file(sh, module_name);
Joshua Brindledf77db42009-01-05 05:37:06 -0500180}
181
Joshua Brindle13cd4c82008-08-19 15:30:36 -0400182int semanage_module_remove(semanage_handle_t * sh, char *module_name)
183{
184 if (sh->funcs->remove == NULL) {
185 ERR(sh, "No remove function defined for this connection type.");
186 return -1;
187 } else if (!sh->is_connected) {
188 ERR(sh, "Not connected.");
189 return -1;
190 } else if (!sh->is_in_transaction) {
191 if (semanage_begin_transaction(sh) < 0) {
192 return -1;
193 }
194 }
195 sh->modules_modified = 1;
196 return sh->funcs->remove(sh, module_name);
197}
198
199int semanage_module_list(semanage_handle_t * sh,
200 semanage_module_info_t ** modinfo, int *num_modules)
201{
202 if (sh->funcs->list == NULL) {
203 ERR(sh, "No list function defined for this connection type.");
204 return -1;
205 } else if (!sh->is_connected) {
206 ERR(sh, "Not connected.");
207 return -1;
208 }
209 return sh->funcs->list(sh, modinfo, num_modules);
210}
211
212void semanage_module_info_datum_destroy(semanage_module_info_t * modinfo)
213{
214 if (modinfo != NULL) {
Caleb Cased220f492009-12-23 18:25:54 -0500215 modinfo->priority = 0;
216
Joshua Brindle13cd4c82008-08-19 15:30:36 -0400217 free(modinfo->name);
Caleb Cased220f492009-12-23 18:25:54 -0500218 modinfo->name = NULL;
219
Caleb Cased220f492009-12-23 18:25:54 -0500220 free(modinfo->lang_ext);
221 modinfo->lang_ext = NULL;
222
223 modinfo->enabled = -1;
Joshua Brindle13cd4c82008-08-19 15:30:36 -0400224 }
225}
226
227hidden_def(semanage_module_info_datum_destroy)
228
229semanage_module_info_t *semanage_module_list_nth(semanage_module_info_t * list,
230 int n)
231{
232 return list + n;
233}
234
235hidden_def(semanage_module_list_nth)
236
237const char *semanage_module_get_name(semanage_module_info_t * modinfo)
238{
239 return modinfo->name;
240}
241
242hidden_def(semanage_module_get_name)
243
Steve Lawrenced5bcc222011-10-14 15:29:29 -0400244/* Legacy function that remains to preserve ABI
245 * compatibility.
246 */
247const char *semanage_module_get_version(semanage_module_info_t * modinfo
248 __attribute__ ((unused)))
Joshua Brindle13cd4c82008-08-19 15:30:36 -0400249{
Steve Lawrenced5bcc222011-10-14 15:29:29 -0400250 return "";
Joshua Brindle13cd4c82008-08-19 15:30:36 -0400251}
252
Caleb Cased220f492009-12-23 18:25:54 -0500253int semanage_module_info_create(semanage_handle_t *sh,
254 semanage_module_info_t **modinfo)
255{
256 assert(sh);
257 assert(modinfo);
258
259 *modinfo = malloc(sizeof(semanage_module_info_t));
260 if (*modinfo == NULL) return -1;
261
262 return semanage_module_info_init(sh, *modinfo);
263}
264
Caleb Case1875c852009-12-23 18:25:58 -0500265hidden_def(semanage_module_info_create)
266
Caleb Cased220f492009-12-23 18:25:54 -0500267int semanage_module_info_destroy(semanage_handle_t *sh,
268 semanage_module_info_t *modinfo)
269{
270 assert(sh);
271
272 if (!modinfo) {
273 return 0;
274 }
275
276 free(modinfo->name);
Caleb Cased220f492009-12-23 18:25:54 -0500277 free(modinfo->lang_ext);
278
279 return semanage_module_info_init(sh, modinfo);
280}
281
Caleb Case1875c852009-12-23 18:25:58 -0500282hidden_def(semanage_module_info_destroy)
283
Caleb Cased220f492009-12-23 18:25:54 -0500284int semanage_module_info_init(semanage_handle_t *sh,
285 semanage_module_info_t *modinfo)
286{
287 assert(sh);
288 assert(modinfo);
289
290 modinfo->priority = 0;
291 modinfo->name = NULL;
Caleb Cased220f492009-12-23 18:25:54 -0500292 modinfo->lang_ext = NULL;
293 modinfo->enabled = -1;
294
295 return 0;
296}
297
298int semanage_module_info_clone(semanage_handle_t *sh,
299 const semanage_module_info_t *source,
300 semanage_module_info_t *target)
301{
302 assert(sh);
303 assert(source);
304 assert(target);
305
306 int status = 0;
307 int ret = 0;
308
309 ret = semanage_module_info_destroy(sh, target);
310 if (ret != 0) {
311 status = -1;
312 goto cleanup;
313 }
314
315 ret = semanage_module_info_set_priority(sh, target, source->priority);
316 if (ret != 0) {
317 status = -1;
318 goto cleanup;
319 }
320
321 ret = semanage_module_info_set_name(sh, target, source->name);
322 if (ret != 0) {
323 status = -1;
324 goto cleanup;
325 }
326
Caleb Cased220f492009-12-23 18:25:54 -0500327 ret = semanage_module_info_set_lang_ext(sh, target, source->lang_ext);
328 if (ret != 0) {
329 status = -1;
330 goto cleanup;
331 }
332
333 ret = semanage_module_info_set_enabled(sh, target, source->enabled);
334 if (ret != 0) {
335 status = -1;
336 goto cleanup;
337 }
338
339cleanup:
340 if (status != 0) semanage_module_info_destroy(sh, target);
341 return status;
342}
343
344int semanage_module_info_get_priority(semanage_handle_t *sh,
345 semanage_module_info_t *modinfo,
346 uint16_t *priority)
347{
348 assert(sh);
349 assert(modinfo);
350 assert(priority);
351
352 *priority = modinfo->priority;
353
354 return 0;
355}
356
Caleb Case1875c852009-12-23 18:25:58 -0500357hidden_def(semanage_module_info_get_priority)
358
Caleb Cased220f492009-12-23 18:25:54 -0500359int semanage_module_info_get_name(semanage_handle_t *sh,
360 semanage_module_info_t *modinfo,
361 const char **name)
362{
363 assert(sh);
364 assert(modinfo);
365 assert(name);
366
367 *name = modinfo->name;
368
369 return 0;
370}
371
Caleb Case1875c852009-12-23 18:25:58 -0500372hidden_def(semanage_module_info_get_name)
373
Caleb Cased220f492009-12-23 18:25:54 -0500374int semanage_module_info_get_lang_ext(semanage_handle_t *sh,
375 semanage_module_info_t *modinfo,
376 const char **lang_ext)
377{
378 assert(sh);
379 assert(modinfo);
380 assert(lang_ext);
381
382 *lang_ext = modinfo->lang_ext;
383
384 return 0;
385}
386
Caleb Case1875c852009-12-23 18:25:58 -0500387hidden_def(semanage_module_info_get_lang_ext)
388
Caleb Cased220f492009-12-23 18:25:54 -0500389int semanage_module_info_get_enabled(semanage_handle_t *sh,
390 semanage_module_info_t *modinfo,
391 int *enabled)
392{
393 assert(sh);
394 assert(modinfo);
395 assert(enabled);
396
397 *enabled = modinfo->enabled;
398
399 return 0;
400}
401
Caleb Case1875c852009-12-23 18:25:58 -0500402hidden_def(semanage_module_info_get_enabled)
403
Caleb Cased220f492009-12-23 18:25:54 -0500404int semanage_module_info_set_priority(semanage_handle_t *sh,
405 semanage_module_info_t *modinfo,
406 uint16_t priority)
407{
408 assert(sh);
409 assert(modinfo);
410
411 /* Verify priority */
412 if (semanage_module_validate_priority(priority) < 0) {
413 errno = 0;
414 ERR(sh, "Priority %d is invalid.", priority);
415 return -1;
416 }
417
418 modinfo->priority = priority;
419
420 return 0;
421}
422
Caleb Case1875c852009-12-23 18:25:58 -0500423hidden_def(semanage_module_info_set_priority)
424
Caleb Cased220f492009-12-23 18:25:54 -0500425int semanage_module_info_set_name(semanage_handle_t *sh,
426 semanage_module_info_t *modinfo,
427 const char *name)
428{
429 assert(sh);
430 assert(modinfo);
431 assert(name);
432
433 char * tmp;
434
435 /* Verify name */
436 if (semanage_module_validate_name(name) < 0) {
437 errno = 0;
438 ERR(sh, "Name %s is invalid.", name);
439 return -1;
440 }
441
442 tmp = strdup(name);
443 if (!tmp) {
444 return -1;
445 }
446
447 free(modinfo->name);
448 modinfo->name = tmp;
449
450 return 0;
451}
452
Caleb Case1875c852009-12-23 18:25:58 -0500453hidden_def(semanage_module_info_set_name)
454
Caleb Cased220f492009-12-23 18:25:54 -0500455int semanage_module_info_set_lang_ext(semanage_handle_t *sh,
456 semanage_module_info_t *modinfo,
457 const char *lang_ext)
458{
459 assert(sh);
460 assert(modinfo);
461 assert(lang_ext);
462
463 char * tmp;
464
465 /* Verify extension */
466 if (semanage_module_validate_lang_ext(lang_ext) < 0) {
467 errno = 0;
468 ERR(sh, "Language extensions %s is invalid.", lang_ext);
469 return -1;
470 }
471
472 tmp = strdup(lang_ext);
473 if (!tmp) {
474 return -1;
475 }
476
477 free(modinfo->lang_ext);
478 modinfo->lang_ext = tmp;
479
480 return 0;
481}
482
Caleb Case1875c852009-12-23 18:25:58 -0500483hidden_def(semanage_module_info_set_lang_ext)
484
Caleb Cased220f492009-12-23 18:25:54 -0500485int semanage_module_info_set_enabled(semanage_handle_t *sh,
486 semanage_module_info_t *modinfo,
487 int enabled)
488{
489 assert(sh);
490 assert(modinfo);
491
492 /* Verify enabled */
493 if (semanage_module_validate_enabled(enabled) < 0) {
494 errno = 0;
495 ERR(sh, "Enabled status %d is invalid.", enabled);
496 return -1;
497 }
498
499 modinfo->enabled = enabled;
500
501 return 0;
502}
503
Caleb Case1875c852009-12-23 18:25:58 -0500504hidden_def(semanage_module_info_set_enabled)
505
Caleb Cased220f492009-12-23 18:25:54 -0500506int semanage_module_get_path(semanage_handle_t *sh,
507 const semanage_module_info_t *modinfo,
508 enum semanage_module_path_type type,
509 char *path,
510 size_t len)
511{
512 assert(sh);
513 assert(modinfo);
514 assert(path);
515
516 int status = 0;
517 int ret = 0;
518
519 const char *modules_path = NULL;
520 const char *file = NULL;
521
522 modules_path = sh->is_in_transaction ?
523 semanage_path(SEMANAGE_TMP, SEMANAGE_MODULES):
524 semanage_path(SEMANAGE_ACTIVE, SEMANAGE_MODULES);
525
526 switch (type) {
527 case SEMANAGE_MODULE_PATH_PRIORITY:
528 /* verify priority */
529 ret = semanage_module_validate_priority(modinfo->priority);
530 if (ret < 0) {
531 errno = 0;
532 ERR(sh,
533 "Priority %d is invalid.",
534 modinfo->priority);
535 status = ret;
536 goto cleanup;
537 }
538
539 ret = snprintf(path,
540 len,
541 "%s/%03u",
542 modules_path,
543 modinfo->priority);
544 if (ret < 0 || (size_t)ret >= len) {
545 ERR(sh, "Unable to compose priority path.");
546 status = -1;
547 goto cleanup;
548 }
549 break;
550 case SEMANAGE_MODULE_PATH_NAME:
551 /* verify priority and name */
552 ret = semanage_module_validate_priority(modinfo->priority);
553 if (ret < 0) {
554 errno = 0;
555 ERR(sh,
556 "Priority %d is invalid.",
557 modinfo->priority);
558 status = -1;
559 goto cleanup;
560 }
561
562 ret = semanage_module_validate_name(modinfo->name);
563 if (ret < 0) {
564 errno = 0;
565 ERR(sh, "Name %s is invalid.", modinfo->name);
566 status = -1;
567 goto cleanup;
568 }
569
570 ret = snprintf(path,
571 len,
572 "%s/%03u/%s",
573 modules_path,
574 modinfo->priority,
575 modinfo->name);
576 if (ret < 0 || (size_t)ret >= len) {
577 ERR(sh, "Unable to compose name path.");
578 status = -1;
579 goto cleanup;
580 }
581 break;
582 case SEMANAGE_MODULE_PATH_HLL:
583 /* verify priority, name, and ext */
584 ret = semanage_module_validate_lang_ext(modinfo->lang_ext);
585 if (ret < 0) {
586 errno = 0;
587 ERR(sh,
588 "Language extensions %s is invalid.",
589 modinfo->lang_ext);
590 status = -1;
591 goto cleanup;
592 }
593
594 ret = semanage_module_validate_priority(modinfo->priority);
595 if (ret < 0) {
596 errno = 0;
597 ERR(sh,
598 "Priority %d is invalid.",
599 modinfo->priority);
600 status = -1;
601 goto cleanup;
602 }
603
604 ret = semanage_module_validate_name(modinfo->name);
605 if (ret < 0) {
606 errno = 0;
607 ERR(sh, "Name %s is invalid.", modinfo->name);
608 status = -1;
609 goto cleanup;
610 }
611
612 ret = snprintf(path,
613 len,
614 "%s/%03u/%s/%s.%s",
615 modules_path,
616 modinfo->priority,
617 modinfo->name,
618 modinfo->name,
619 modinfo->lang_ext);
620 if (ret < 0 || (size_t)ret >= len) {
621 ERR(sh, "Unable to compose hll path.");
622 status = -1;
623 goto cleanup;
624 }
625 break;
626 case SEMANAGE_MODULE_PATH_CIL:
627 if (file == NULL) file = "cil";
628 case SEMANAGE_MODULE_PATH_LANG_EXT:
629 if (file == NULL) file = "lang_ext";
Caleb Cased220f492009-12-23 18:25:54 -0500630
631 /* verify priority and name */
632 ret = semanage_module_validate_priority(modinfo->priority);
633 if (ret < 0) {
634 errno = 0;
635 ERR(sh,
636 "Priority %d is invalid.",
637 modinfo->priority);
638 status = -1;
639 goto cleanup;
640 }
641
642 ret = semanage_module_validate_name(modinfo->name);
643 if (ret < 0) {
644 errno = 0;
645 ERR(sh, "Name %s is invalid.", modinfo->name);
646 status = -1;
647 goto cleanup;
648 }
649
650 ret = snprintf(path,
651 len,
652 "%s/%03u/%s/%s",
653 modules_path,
654 modinfo->priority,
655 modinfo->name,
656 file);
657 if (ret < 0 || (size_t)ret >= len) {
658 ERR(sh,
659 "Unable to compose path for %s file.",
660 file);
661 status = -1;
662 goto cleanup;
663 }
664 break;
665 case SEMANAGE_MODULE_PATH_DISABLED:
666 /* verify name */
667 ret = semanage_module_validate_name(modinfo->name);
668 if (ret < 0) {
669 errno = 0;
670 ERR(sh, "Name %s is invalid.", modinfo->name);
671 status = -1;
672 goto cleanup;
673 }
674
675 ret = snprintf(path,
676 len,
677 "%s/disabled/%s",
678 modules_path,
679 modinfo->name);
680 if (ret < 0 || (size_t)ret >= len) {
681 ERR(sh,
682 "Unable to compose disabled status path.");
683 status = -1;
684 goto cleanup;
685 }
686 break;
687 default:
688 ERR(sh, "Invalid module path type %d.", type);
689 status = -1;
690 goto cleanup;
691 }
692
693cleanup:
694 return status;
695}
696
697int semanage_module_key_create(semanage_handle_t *sh,
698 semanage_module_key_t **modkey)
699{
700 assert(sh);
701 assert(modkey);
702
703 *modkey = malloc(sizeof(semanage_module_key_t));
704 if (*modkey == NULL) return -1;
705
706 return semanage_module_key_init(sh, *modkey);
707}
708
Caleb Case1875c852009-12-23 18:25:58 -0500709hidden_def(semanage_module_key_create)
710
Caleb Cased220f492009-12-23 18:25:54 -0500711int semanage_module_key_destroy(semanage_handle_t *sh,
712 semanage_module_key_t *modkey)
713{
714 assert(sh);
715
716 if (modkey) {
717 free(modkey->name);
718 }
719
720 return semanage_module_key_init(sh, modkey);
721}
722
Caleb Case1875c852009-12-23 18:25:58 -0500723hidden_def(semanage_module_key_destroy)
724
Caleb Cased220f492009-12-23 18:25:54 -0500725int semanage_module_key_init(semanage_handle_t *sh,
726 semanage_module_key_t *modkey)
727{
728 assert(sh);
729 assert(modkey);
730
731 modkey->name = NULL;
732 modkey->priority = 0;
733
734 return 0;
735}
736
737int semanage_module_key_get_name(semanage_handle_t *sh,
738 semanage_module_key_t *modkey,
739 const char **name)
740{
741 assert(sh);
742 assert(modkey);
743 assert(name);
744
745 *name = modkey->name;
746
747 return 0;
748}
749
Caleb Case1875c852009-12-23 18:25:58 -0500750hidden_def(semanage_module_key_get_name)
751
Caleb Cased220f492009-12-23 18:25:54 -0500752int semanage_module_key_get_priority(semanage_handle_t *sh,
753 semanage_module_key_t *modkey,
754 uint16_t *priority)
755{
756 assert(sh);
757 assert(modkey);
758 assert(priority);
759
760 *priority = modkey->priority;
761
762 return 0;
763}
764
Caleb Case1875c852009-12-23 18:25:58 -0500765hidden_def(semanage_module_key_get_priority)
766
Caleb Cased220f492009-12-23 18:25:54 -0500767int semanage_module_key_set_name(semanage_handle_t *sh,
768 semanage_module_key_t *modkey,
769 const char *name)
770{
771 assert(sh);
772 assert(modkey);
773 assert(name);
774
775 int status = 0;
776 char *tmp = NULL;
777
778 if (semanage_module_validate_name(name) < 0) {
779 errno = 0;
780 ERR(sh, "Name %s is invalid.", name);
781 return -1;
782 }
783
784 tmp = strdup(name);
785 if (tmp == NULL) {
786 status = -1;
787 goto cleanup;
788 }
789
790 free(modkey->name);
791 modkey->name = tmp;
792
793cleanup:
794 return status;
795}
796
Caleb Case1875c852009-12-23 18:25:58 -0500797hidden_def(semanage_module_key_set_name)
798
Caleb Cased220f492009-12-23 18:25:54 -0500799int semanage_module_key_set_priority(semanage_handle_t *sh,
800 semanage_module_key_t *modkey,
801 uint16_t priority)
802{
803 assert(sh);
804 assert(modkey);
805
806 if (semanage_module_validate_priority(priority) < 0) {
807 errno = 0;
808 ERR(sh, "Priority %d is invalid.", priority);
809 return -1;
810 }
811
812 modkey->priority = priority;
813
814 return 0;
815}
816
Caleb Case1875c852009-12-23 18:25:58 -0500817hidden_def(semanage_module_key_set_priority)
818
Steve Lawrence9fbc6d12014-06-13 13:20:26 -0400819int semanage_module_get_enabled_1_1(semanage_handle_t *sh,
Caleb Cased4048fa2009-12-23 18:25:55 -0500820 const semanage_module_key_t *modkey,
821 int *enabled)
822{
823 assert(sh);
824 assert(modkey);
825 assert(enabled);
826
827 if (sh->funcs->get_enabled == NULL) {
828 ERR(sh,
829 "No get_enabled function defined for this connection type.");
830 return -1;
831 } else if (!sh->is_connected) {
832 ERR(sh, "Not connected.");
833 return -1;
834 }
835
836 return sh->funcs->get_enabled(sh, modkey, enabled);
837}
838
Steve Lawrence9fbc6d12014-06-13 13:20:26 -0400839int semanage_module_get_enabled_1_0(semanage_module_info_t *modinfo)
840{
841 return modinfo->enabled;
842}
Caleb Case1875c852009-12-23 18:25:58 -0500843
Caleb Cased4048fa2009-12-23 18:25:55 -0500844int semanage_module_set_enabled(semanage_handle_t *sh,
845 const semanage_module_key_t *modkey,
846 int enabled)
847{
848 assert(sh);
849 assert(modkey);
850
851 if (sh->funcs->set_enabled == NULL) {
852 ERR(sh,
853 "No set_enabled function defined for this connection type.");
854 return -1;
855 } else if (!sh->is_connected) {
856 ERR(sh, "Not connected.");
857 return -1;
858 } else if (!sh->is_in_transaction) {
859 if (semanage_begin_transaction(sh) < 0) {
860 return -1;
861 }
862 }
863
864 sh->modules_modified = 1;
865 return sh->funcs->set_enabled(sh, modkey, enabled);
866}
Caleb Cased220f492009-12-23 18:25:54 -0500867
Caleb Case1875c852009-12-23 18:25:58 -0500868hidden_def(semanage_module_set_enabled)
869
Steve Lawrence9fbc6d12014-06-13 13:20:26 -0400870/* This function exists only for ABI compatability. It has been deprecated and
871 * should not be used. Instead, use semanage_module_set_enabled() */
872int semanage_module_enable(semanage_handle_t *sh, char *module_name)
873{
874 int rc = -1;
875 semanage_module_key_t *modkey = NULL;
876
877 rc = semanage_module_key_create(sh, &modkey);
878 if (rc != 0)
879 goto exit;
880
881 rc = semanage_module_key_set_name(sh, modkey, module_name);
882 if (rc != 0)
883 goto exit;
884
885 rc = semanage_module_set_enabled(sh, modkey, 1);
886 if (rc != 0)
887 goto exit;
888
889 rc = 0;
890
891exit:
892 semanage_module_key_destroy(sh, modkey);
893 free(modkey);
894
895 return rc;
896}
897
898/* This function exists only for ABI compatability. It has been deprecated and
899 * should not be used. Instead, use semanage_module_set_enabled() */
900int semanage_module_disable(semanage_handle_t *sh, char *module_name)
901{
902 int rc = -1;
903 semanage_module_key_t *modkey = NULL;
904
905 rc = semanage_module_key_create(sh, &modkey);
906 if (rc != 0)
907 goto exit;
908
909 rc = semanage_module_key_set_name(sh, modkey, module_name);
910 if (rc != 0)
911 goto exit;
912
913 rc = semanage_module_set_enabled(sh, modkey, 0);
914 if (rc != 0)
915 goto exit;
916
917 rc = 0;
918
919exit:
920 semanage_module_key_destroy(sh, modkey);
921 free(modkey);
922
923 return rc;
924}
925
Caleb Cased220f492009-12-23 18:25:54 -0500926/* Converts a string to a priority
927 *
928 * returns -1 if str is not a valid priority.
929 * returns 0 and sets priority if str is a valid priority
930 */
931int semanage_string_to_priority(const char *str, uint16_t *priority)
932{
933 unsigned long val;
934 char *endptr = NULL;
935 int status = -1;
936
937 if (str == NULL || priority == NULL) {
938 goto exit;
939 }
940
941 errno = 0;
942
943 val = strtoul(str, &endptr, 10);
944
945 if (errno != 0 || endptr == str || *endptr != '\0' || val > UINT16_MAX) {
946 goto exit;
947 }
948
949 if (semanage_module_validate_priority((uint16_t)val) < 0) {
950 goto exit;
951 }
952
953 *priority = val;
954 status = 0;
955
956exit:
957 return status;
958}
959
960/* Validates a module info struct.
961 *
962 * Returns -1 if module is invalid, 0 otherwise.
963 */
964int semanage_module_info_validate(const semanage_module_info_t *modinfo)
965{
966 if (semanage_module_validate_priority(modinfo->priority) != 0 ||
967 semanage_module_validate_name(modinfo->name) != 0 ||
Caleb Cased220f492009-12-23 18:25:54 -0500968 semanage_module_validate_lang_ext(modinfo->lang_ext) != 0 ||
969 semanage_module_validate_enabled(modinfo->enabled) != 0) {
970 return -1;
971 }
972 return 0;
973}
974
Caleb Case73430e52009-12-23 18:25:53 -0500975#define PRIORITY_MIN 1
976#define PRIORITY_MAX 999
977
978/* Validates priority.
979 *
980 * returns -1 if priority is not in the valid range, returns 0 otherwise
981 */
982int semanage_module_validate_priority(uint16_t priority)
983{
984 if (priority >= PRIORITY_MIN && priority <= PRIORITY_MAX) {
985 return 0;
986 }
987
988 return -1;
989}
990
Caleb Cased220f492009-12-23 18:25:54 -0500991/* Validates module name.
992 *
993 * A module name must match one of the following regular expressions
994 * to be considered valid:
995 *
996 * ^[a-zA-Z](\.?[a-zA-Z0-9_-])*$
Caleb Cased220f492009-12-23 18:25:54 -0500997 *
998 * returns -1 if name is not valid, returns 0 otherwise
999 */
1000int semanage_module_validate_name(const char * name)
1001{
1002 int status = 0;
1003
1004 if (name == NULL) {
1005 status = -1;
1006 goto exit;
1007 }
1008
Caleb Cased220f492009-12-23 18:25:54 -05001009 if (!isalpha(*name)) {
1010 status = -1;
1011 goto exit;
1012 }
1013
1014#define ISVALIDCHAR(c) (isalnum(c) || c == '_' || c == '-')
1015
1016 for (name++; *name; name++) {
1017 if (ISVALIDCHAR(*name)) {
1018 continue;
1019 }
1020 if (*name == '.' && name++ && ISVALIDCHAR(*name)) {
1021 continue;
1022 }
1023 status = -1;
1024 goto exit;
1025 }
1026
1027#undef ISVALIDCHAR
1028
1029exit:
1030 return status;
1031}
1032
1033/* Validates module enabled status.
1034 *
1035 * Valid enabled values are 1, 0, and -1.
1036 *
1037 * returns 0 if enabled is a valid value, returns -1 otherwise.
1038 */
1039int semanage_module_validate_enabled(int enabled)
1040{
1041 if (enabled == 1 || enabled == 0 || enabled == -1) {
1042 return 0;
1043 }
1044
1045 return -1;
1046}
1047
1048/* Validate extension.
1049 *
1050 * An extension must match the following regular expression to be
1051 * considered valid:
1052 *
1053 * ^[a-zA-Z0-9][a-zA-Z0-9_-]*$
1054 *
1055 * returns 0 if ext is a valid value, returns -1 otherwise.
1056 */
1057int semanage_module_validate_lang_ext(const char *ext)
1058{
1059 int status = 0;
1060
1061 if (ext == NULL) {
1062 status = -1;
1063 goto exit;
1064 }
1065
1066 if (!isalnum(*ext)) {
1067 status = -1;
1068 goto exit;
1069 }
1070
1071#define ISVALIDCHAR(c) (isalnum(c) || c == '_' || c == '-')
1072
1073 for (ext++; *ext; ext++) {
1074 if (ISVALIDCHAR(*ext)) {
1075 continue;
1076 }
1077 status = -1;
1078 goto exit;
1079 }
1080
1081#undef ISVALIDCHAR
1082
1083exit:
1084 return status;
1085}
1086
Caleb Cased4048fa2009-12-23 18:25:55 -05001087int semanage_module_get_module_info(semanage_handle_t *sh,
1088 const semanage_module_key_t *modkey,
1089 semanage_module_info_t **modinfo)
1090{
1091 assert(sh);
1092 assert(modkey);
1093 assert(modinfo);
1094
1095 if (sh->funcs->get_module_info == NULL) {
1096 ERR(sh,
1097 "No get module info function defined for this connection type.");
1098 return -1;
1099 } else if (!sh->is_connected) {
1100 ERR(sh, "Not connected.");
1101 return -1;
1102 }
1103
1104 return sh->funcs->get_module_info(sh, modkey, modinfo);
1105}
1106
1107int semanage_module_list_all(semanage_handle_t *sh,
1108 semanage_module_info_t **modinfos,
1109 int *modinfos_len)
1110{
1111 assert(sh);
1112 assert(modinfos);
1113 assert(modinfos_len);
1114
1115 if (sh->funcs->list_all == NULL) {
1116 ERR(sh,
1117 "No list all function defined for this connection type.");
1118 return -1;
1119 } else if (!sh->is_connected) {
1120 ERR(sh, "Not connected.");
1121 return -1;
1122 }
1123
1124 return sh->funcs->list_all(sh, modinfos, modinfos_len);
1125}
1126
Caleb Casebb5121e2009-12-23 18:25:57 -05001127int semanage_module_install_info(semanage_handle_t *sh,
1128 const semanage_module_info_t *modinfo,
1129 char *data,
1130 size_t data_len)
1131{
1132 if (sh->funcs->install_info == NULL) {
1133 ERR(sh,
1134 "No install info function defined for this connection type.");
1135 return -1;
1136 } else if (!sh->is_connected) {
1137 ERR(sh, "Not connected.");
1138 return -1;
1139 } else if (!sh->is_in_transaction) {
1140 if (semanage_begin_transaction(sh) < 0) {
1141 return -1;
1142 }
1143 }
1144 sh->modules_modified = 1;
1145 return sh->funcs->install_info(sh, modinfo, data, data_len);
1146}
1147
1148int semanage_module_remove_key(semanage_handle_t *sh,
1149 const semanage_module_key_t *modkey)
1150{
1151 if (sh->funcs->remove_key== NULL) {
1152 ERR(sh,
1153 "No remove key function defined for this connection type.");
1154 return -1;
1155 } else if (!sh->is_connected) {
1156 ERR(sh, "Not connected.");
1157 return -1;
1158 } else if (!sh->is_in_transaction) {
1159 if (semanage_begin_transaction(sh) < 0) {
1160 return -1;
1161 }
1162 }
1163 sh->modules_modified = 1;
1164 return sh->funcs->remove_key(sh, modkey);
1165}
1166