source: rtems-libbsd/freebsd/lib/libc/posix1e/mac.c @ 3d1e767

55-freebsd-126-freebsd-12freebsd-9.3
Last change on this file since 3d1e767 was 3d1e767, checked in by Sebastian Huber <sebastian.huber@…>, on 04/27/16 at 08:25:22

Directly use <sys/types.h> provided by Newlib

  • Property mode set to 100644
File size: 9.2 KB
Line 
1#include <machine/rtems-bsd-user-space.h>
2
3/*
4 * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson
5 * Copyright (c) 2002, 2003 Networks Associates Technology, Inc.
6 * All rights reserved.
7 *
8 * This software was developed by Robert Watson for the TrustedBSD Project.
9 *
10 * This software was developed for the FreeBSD Project in part by Network
11 * Associates Laboratories, the Security Research Division of Network
12 * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"),
13 * as part of the DARPA CHATS research program.
14 *
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions
17 * are met:
18 * 1. Redistributions of source code must retain the above copyright
19 *    notice, this list of conditions and the following disclaimer.
20 * 2. Redistributions in binary form must reproduce the above copyright
21 *    notice, this list of conditions and the following disclaimer in the
22 *    documentation and/or other materials provided with the distribution.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 */
36
37#include <sys/cdefs.h>
38__FBSDID("$FreeBSD$");
39
40#include <sys/types.h>
41#include <sys/queue.h>
42#include <sys/sysctl.h>
43
44#include <dlfcn.h>
45#include <errno.h>
46#include <limits.h>
47#include <stdio.h>
48#include <stdlib.h>
49#include <string.h>
50#include <unistd.h>
51
52#include <sys/mac.h>
53
54static int      internal_initialized;
55
56/*
57 * Maintain a list of default label preparations for various object
58 * types.  Each name will appear only once in the list.
59 *
60 * XXXMAC: Not thread-safe.
61 */
62static LIST_HEAD(, label_default) label_default_head;
63struct label_default {
64        char                            *ld_name;
65        char                            *ld_labels;
66        LIST_ENTRY(label_default)        ld_entries;
67};
68
69static void
70mac_destroy_labels(void)
71{
72        struct label_default *ld;
73
74        while ((ld = LIST_FIRST(&label_default_head))) {
75                free(ld->ld_name);
76                free(ld->ld_labels);
77                LIST_REMOVE(ld, ld_entries);
78                free(ld);
79        }
80}
81
82static void
83mac_destroy_internal(void)
84{
85
86        mac_destroy_labels();
87
88        internal_initialized = 0;
89}
90
91static int
92mac_add_type(const char *name, const char *labels)
93{
94        struct label_default *ld, *ld_new;
95        char *name_dup, *labels_dup;
96
97        /*
98         * Speculatively allocate all the memory now to avoid allocating
99         * later when we will someday hold a mutex.
100         */
101        name_dup = strdup(name);
102        if (name_dup == NULL) {
103                errno = ENOMEM;
104                return (-1);
105        }
106        labels_dup = strdup(labels);
107        if (labels_dup == NULL) {
108                free(name_dup);
109                errno = ENOMEM;
110                return (-1);
111        }
112        ld_new = malloc(sizeof(*ld));
113        if (ld_new == NULL) {
114                free(name_dup);
115                free(labels_dup);
116                errno = ENOMEM;
117                return (-1);
118        }
119
120        /*
121         * If the type is already present, replace the current entry
122         * rather than add a new instance.
123         */
124        for (ld = LIST_FIRST(&label_default_head); ld != NULL;
125            ld = LIST_NEXT(ld, ld_entries)) {
126                if (strcmp(name, ld->ld_name) == 0)
127                        break;
128        }
129
130        if (ld != NULL) {
131                free(ld->ld_labels);
132                ld->ld_labels = labels_dup;
133                labels_dup = NULL;
134        } else {
135                ld = ld_new;
136                ld->ld_name = name_dup;
137                ld->ld_labels = labels_dup;
138
139                ld_new = NULL;
140                name_dup = NULL;
141                labels_dup = NULL;
142
143                LIST_INSERT_HEAD(&label_default_head, ld, ld_entries);
144        }
145
146        if (name_dup != NULL)
147                free(name_dup);
148        if (labels_dup != NULL)
149                free(labels_dup);
150        if (ld_new != NULL)
151                free(ld_new);
152
153        return (0);
154}
155
156static char *
157next_token(char **string)
158{
159        char *token;
160
161        token = strsep(string, " \t");
162        while (token != NULL && *token == '\0')
163                token = strsep(string, " \t");
164
165        return (token);
166}
167
168static int
169mac_init_internal(int ignore_errors)
170{
171        const char *filename;
172        char line[LINE_MAX];
173        FILE *file;
174        int error;
175
176        error = 0;
177
178        LIST_INIT(&label_default_head);
179
180        if (!issetugid() && getenv("MAC_CONFFILE") != NULL)
181                filename = getenv("MAC_CONFFILE");
182        else
183                filename = MAC_CONFFILE;
184        file = fopen(filename, "r");
185        if (file == NULL)
186                return (0);
187
188        while (fgets(line, LINE_MAX, file)) {
189                char *comment, *parse, *statement;
190
191                if (line[strlen(line)-1] == '\n')
192                        line[strlen(line)-1] = '\0';
193                else {
194                        if (ignore_errors)
195                                continue;
196                        fclose(file);
197                        error = EINVAL;
198                        goto just_return;
199                }
200
201                /* Remove any comment. */
202                comment = line;
203                parse = strsep(&comment, "#");
204
205                /* Blank lines OK. */
206                statement = next_token(&parse);
207                if (statement == NULL)
208                        continue;
209
210                if (strcmp(statement, "default_labels") == 0) {
211                        char *name, *labels;
212
213                        name = next_token(&parse);
214                        labels = next_token(&parse);
215                        if (name == NULL || labels == NULL ||
216                            next_token(&parse) != NULL) {
217                                if (ignore_errors)
218                                        continue;
219                                error = EINVAL;
220                                fclose(file);
221                                goto just_return;
222                        }
223
224                        if (mac_add_type(name, labels) == -1) {
225                                if (ignore_errors)
226                                        continue;
227                                fclose(file);
228                                goto just_return;
229                        }
230                } else if (strcmp(statement, "default_ifnet_labels") == 0 ||
231                    strcmp(statement, "default_file_labels") == 0 ||
232                    strcmp(statement, "default_process_labels") == 0) {
233                        char *labels, *type;
234
235                        if (strcmp(statement, "default_ifnet_labels") == 0)
236                                type = "ifnet";
237                        else if (strcmp(statement, "default_file_labels") == 0)
238                                type = "file";
239                        else if (strcmp(statement, "default_process_labels") ==
240                            0)
241                                type = "process";
242
243                        labels = next_token(&parse);
244                        if (labels == NULL || next_token(&parse) != NULL) {
245                                if (ignore_errors)
246                                        continue;
247                                error = EINVAL;
248                                fclose(file);
249                                goto just_return;
250                        }
251
252                        if (mac_add_type(type, labels) == -1) {
253                                if (ignore_errors)
254                                        continue;
255                                fclose(file);
256                                goto just_return;
257                        }
258                } else {
259                        if (ignore_errors)
260                                continue;
261                        fclose(file);
262                        error = EINVAL;
263                        goto just_return;
264                }
265        }
266
267        fclose(file);
268
269        internal_initialized = 1;
270
271just_return:
272        if (error != 0)
273                mac_destroy_internal();
274        return (error);
275}
276
277static int
278mac_maybe_init_internal(void)
279{
280
281        if (!internal_initialized)
282                return (mac_init_internal(1));
283        else
284                return (0);
285}
286
287int
288mac_reload(void)
289{
290
291        if (internal_initialized)
292                mac_destroy_internal();
293        return (mac_init_internal(0));
294}
295
296int
297mac_free(struct mac *mac)
298{
299
300        if (mac->m_string != NULL)
301                free(mac->m_string);
302        free(mac);
303
304        return (0);
305}
306
307int
308mac_from_text(struct mac **mac, const char *text)
309{
310
311        *mac = (struct mac *) malloc(sizeof(**mac));
312        if (*mac == NULL)
313                return (ENOMEM);
314
315        (*mac)->m_string = strdup(text);
316        if ((*mac)->m_string == NULL) {
317                free(*mac);
318                *mac = NULL;
319                return (ENOMEM);
320        }
321
322        (*mac)->m_buflen = strlen((*mac)->m_string)+1;
323
324        return (0);
325}
326
327int
328mac_to_text(struct mac *mac, char **text)
329{
330
331        *text = strdup(mac->m_string);
332        if (*text == NULL)
333                return (ENOMEM);
334        return (0);
335}
336
337int
338mac_prepare(struct mac **mac, const char *elements)
339{
340
341        if (strlen(elements) >= MAC_MAX_LABEL_BUF_LEN)
342                return (EINVAL);
343
344        *mac = (struct mac *) malloc(sizeof(**mac));
345        if (*mac == NULL)
346                return (ENOMEM);
347
348        (*mac)->m_string = malloc(MAC_MAX_LABEL_BUF_LEN);
349        if ((*mac)->m_string == NULL) {
350                free(*mac);
351                *mac = NULL;
352                return (ENOMEM);
353        }
354
355        strcpy((*mac)->m_string, elements);
356        (*mac)->m_buflen = MAC_MAX_LABEL_BUF_LEN;
357
358        return (0);
359}
360
361int
362mac_prepare_type(struct mac **mac, const char *name)
363{
364        struct label_default *ld;
365        int error;
366
367        error = mac_maybe_init_internal();
368        if (error != 0)
369                return (error);
370
371        for (ld = LIST_FIRST(&label_default_head); ld != NULL;
372            ld = LIST_NEXT(ld, ld_entries)) {
373                if (strcmp(name, ld->ld_name) == 0)
374                        return (mac_prepare(mac, ld->ld_labels));
375        }
376
377        errno = ENOENT;
378        return (-1);            /* XXXMAC: ENOLABEL */
379}
380
381int
382mac_prepare_ifnet_label(struct mac **mac)
383{
384
385        return (mac_prepare_type(mac, "ifnet"));
386}
387
388int
389mac_prepare_file_label(struct mac **mac)
390{
391
392        return (mac_prepare_type(mac, "file"));
393}
394
395int
396mac_prepare_packet_label(struct mac **mac)
397{
398
399        return (mac_prepare_type(mac, "packet"));
400}
401
402int
403mac_prepare_process_label(struct mac **mac)
404{
405
406        return (mac_prepare_type(mac, "process"));
407}
408
409/*
410 * Simply test whether the TrustedBSD/MAC MIB tree is present; if so,
411 * return 1 to indicate that the system has MAC enabled overall or for
412 * a given policy.
413 */
414int
415mac_is_present(const char *policyname)
416{
417        int mib[5];
418        size_t siz;
419        char *mibname;
420        int error;
421
422        if (policyname != NULL) {
423                if (policyname[strcspn(policyname, ".=")] != '\0') {
424                        errno = EINVAL;
425                        return (-1);
426                }
427                mibname = malloc(sizeof("security.mac.") - 1 +
428                    strlen(policyname) + sizeof(".enabled"));
429                if (mibname == NULL)
430                        return (-1);
431                strcpy(mibname, "security.mac.");
432                strcat(mibname, policyname);
433                strcat(mibname, ".enabled");
434                siz = 5;
435                error = sysctlnametomib(mibname, mib, &siz);
436                free(mibname);
437        } else {
438                siz = 3;
439                error = sysctlnametomib("security.mac", mib, &siz);
440        }
441        if (error == -1) {
442                switch (errno) {
443                case ENOTDIR:
444                case ENOENT:
445                        return (0);
446                default:
447                        return (error);
448                }
449        }
450        return (1);
451}
Note: See TracBrowser for help on using the repository browser.