1 /* Copyright (C) 2005 Red Hat, Inc. */ 2 3 struct semanage_port; 4 struct semanage_port_key; 5 typedef struct semanage_port record_t; 6 typedef struct semanage_port_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 <strings.h> 16 #include <semanage/handle.h> 17 #include "port_internal.h" 18 #include "context_internal.h" 19 #include "database_file.h" 20 #include "parse_utils.h" 21 #include "debug.h" 22 23 static int port_print(semanage_handle_t * handle, 24 semanage_port_t * port, FILE * str) 25 { 26 27 char *con_str = NULL; 28 29 int low = semanage_port_get_low(port); 30 int high = semanage_port_get_high(port); 31 int proto = semanage_port_get_proto(port); 32 const char *proto_str = semanage_port_get_proto_str(proto); 33 semanage_context_t *con = semanage_port_get_con(port); 34 35 if (fprintf(str, "portcon %s ", proto_str) < 0) 36 goto err; 37 38 if (low == high) { 39 if (fprintf(str, "%d ", low) < 0) 40 goto err; 41 } else { 42 if (fprintf(str, "%d - %d ", low, high) < 0) 43 goto err; 44 } 45 46 if (semanage_context_to_string(handle, con, &con_str) < 0) 47 goto err; 48 if (fprintf(str, "%s\n", con_str) < 0) 49 goto err; 50 51 free(con_str); 52 return STATUS_SUCCESS; 53 54 err: 55 ERR(handle, "could not print port range %u - %u (%s) to stream", 56 low, high, proto_str); 57 free(con_str); 58 return STATUS_ERR; 59 } 60 61 static int port_parse(semanage_handle_t * handle, 62 parse_info_t * info, semanage_port_t * port) 63 { 64 65 int low, high; 66 char *str = NULL; 67 semanage_context_t *con = NULL; 68 69 if (parse_skip_space(handle, info) < 0) 70 goto err; 71 if (!info->ptr) 72 goto last; 73 74 /* Header */ 75 if (parse_assert_str(handle, info, "portcon") < 0) 76 goto err; 77 if (parse_assert_space(handle, info) < 0) 78 goto err; 79 80 /* Protocol */ 81 if (parse_fetch_string(handle, info, &str, ' ') < 0) 82 goto err; 83 if (!strcasecmp(str, "tcp")) 84 semanage_port_set_proto(port, SEMANAGE_PROTO_TCP); 85 else if (!strcasecmp(str, "udp")) 86 semanage_port_set_proto(port, SEMANAGE_PROTO_UDP); 87 else { 88 ERR(handle, "invalid protocol \"%s\" (%s: %u):\n%s", str, 89 info->filename, info->lineno, info->orig_line); 90 goto err; 91 } 92 free(str); 93 str = NULL; 94 95 /* Range/Port */ 96 if (parse_assert_space(handle, info) < 0) 97 goto err; 98 if (parse_fetch_int(handle, info, &low, '-') < 0) 99 goto err; 100 101 /* If range (-) does not follow immediately, require a space 102 * In other words, the space here is optional, but only 103 * in the ranged case, not in the single port case, 104 * so do a custom test */ 105 if (*(info->ptr) && *(info->ptr) != '-') { 106 if (parse_assert_space(handle, info) < 0) 107 goto err; 108 } 109 110 if (parse_optional_ch(info, '-') != STATUS_NODATA) { 111 112 if (parse_skip_space(handle, info) < 0) 113 goto err; 114 if (parse_fetch_int(handle, info, &high, ' ') < 0) 115 goto err; 116 if (parse_assert_space(handle, info) < 0) 117 goto err; 118 semanage_port_set_range(port, low, high); 119 } else 120 semanage_port_set_port(port, low); 121 122 /* Port context */ 123 if (parse_fetch_string(handle, info, &str, ' ') < 0) 124 goto err; 125 if (semanage_context_from_string(handle, str, &con) < 0) { 126 ERR(handle, "invalid security context \"%s\" (%s: %u)\n%s", 127 str, info->filename, info->lineno, info->orig_line); 128 goto err; 129 } 130 if (con == NULL) { 131 ERR(handle, "<<none>> context is not valid " 132 "for ports (%s: %u):\n%s", info->filename, 133 info->lineno, info->orig_line); 134 goto err; 135 } 136 free(str); 137 str = NULL; 138 139 if (semanage_port_set_con(handle, port, con) < 0) 140 goto err; 141 142 if (parse_assert_space(handle, info) < 0) 143 goto err; 144 145 semanage_context_free(con); 146 return STATUS_SUCCESS; 147 148 last: 149 parse_dispose_line(info); 150 return STATUS_NODATA; 151 152 err: 153 ERR(handle, "could not parse port record"); 154 free(str); 155 semanage_context_free(con); 156 parse_dispose_line(info); 157 return STATUS_ERR; 158 } 159 160 /* PORT RECORD: FILE extension: method table */ 161 record_file_table_t SEMANAGE_PORT_FILE_RTABLE = { 162 .parse = port_parse, 163 .print = port_print, 164 }; 165 166 int port_file_dbase_init(semanage_handle_t * handle, 167 const char *path_ro, 168 const char *path_rw, 169 dbase_config_t * dconfig) 170 { 171 172 if (dbase_file_init(handle, 173 path_ro, 174 path_rw, 175 &SEMANAGE_PORT_RTABLE, 176 &SEMANAGE_PORT_FILE_RTABLE, &dconfig->dbase) < 0) 177 return STATUS_ERR; 178 179 dconfig->dtable = &SEMANAGE_FILE_DTABLE; 180 return STATUS_SUCCESS; 181 } 182 183 void port_file_dbase_release(dbase_config_t * dconfig) 184 { 185 186 dbase_file_release(dconfig->dbase); 187 } 188