1 #include <errno.h> 2 #include <stdlib.h> 3 #include <string.h> 4 #include <stdio.h> 5 6 #include "context_internal.h" 7 #include "debug.h" 8 #include "private.h" 9 10 struct sepol_context { 11 12 /* Selinux user */ 13 char *user; 14 15 /* Selinux role */ 16 char *role; 17 18 /* Selinux type */ 19 char *type; 20 21 /* MLS */ 22 char *mls; 23 }; 24 25 /* User */ 26 const char *sepol_context_get_user(const sepol_context_t * con) 27 { 28 29 return con->user; 30 } 31 32 hidden_def(sepol_context_get_user) 33 34 int sepol_context_set_user(sepol_handle_t * handle, 35 sepol_context_t * con, const char *user) 36 { 37 38 char *tmp_user = strdup(user); 39 if (!tmp_user) { 40 ERR(handle, "out of memory, could not set " 41 "context user to %s", user); 42 return STATUS_ERR; 43 } 44 45 free(con->user); 46 con->user = tmp_user; 47 return STATUS_SUCCESS; 48 } 49 50 hidden_def(sepol_context_set_user) 51 52 /* Role */ 53 const char *sepol_context_get_role(const sepol_context_t * con) 54 { 55 56 return con->role; 57 } 58 59 hidden_def(sepol_context_get_role) 60 61 int sepol_context_set_role(sepol_handle_t * handle, 62 sepol_context_t * con, const char *role) 63 { 64 65 char *tmp_role = strdup(role); 66 if (!tmp_role) { 67 ERR(handle, "out of memory, could not set " 68 "context role to %s", role); 69 return STATUS_ERR; 70 } 71 free(con->role); 72 con->role = tmp_role; 73 return STATUS_SUCCESS; 74 } 75 76 hidden_def(sepol_context_set_role) 77 78 /* Type */ 79 const char *sepol_context_get_type(const sepol_context_t * con) 80 { 81 82 return con->type; 83 } 84 85 hidden_def(sepol_context_get_type) 86 87 int sepol_context_set_type(sepol_handle_t * handle, 88 sepol_context_t * con, const char *type) 89 { 90 91 char *tmp_type = strdup(type); 92 if (!tmp_type) { 93 ERR(handle, "out of memory, could not set " 94 "context type to %s", type); 95 return STATUS_ERR; 96 } 97 free(con->type); 98 con->type = tmp_type; 99 return STATUS_SUCCESS; 100 } 101 102 hidden_def(sepol_context_set_type) 103 104 /* MLS */ 105 const char *sepol_context_get_mls(const sepol_context_t * con) 106 { 107 108 return con->mls; 109 } 110 111 hidden_def(sepol_context_get_mls) 112 113 int sepol_context_set_mls(sepol_handle_t * handle, 114 sepol_context_t * con, const char *mls) 115 { 116 117 char *tmp_mls = strdup(mls); 118 if (!tmp_mls) { 119 ERR(handle, "out of memory, could not set " 120 "MLS fields to %s", mls); 121 return STATUS_ERR; 122 } 123 free(con->mls); 124 con->mls = tmp_mls; 125 return STATUS_SUCCESS; 126 } 127 128 hidden_def(sepol_context_set_mls) 129 130 /* Create */ 131 int sepol_context_create(sepol_handle_t * handle, sepol_context_t ** con_ptr) 132 { 133 134 sepol_context_t *con = 135 (sepol_context_t *) malloc(sizeof(sepol_context_t)); 136 137 if (!con) { 138 ERR(handle, "out of memory, could not " "create context\n"); 139 return STATUS_ERR; 140 } 141 142 con->user = NULL; 143 con->role = NULL; 144 con->type = NULL; 145 con->mls = NULL; 146 *con_ptr = con; 147 return STATUS_SUCCESS; 148 } 149 150 hidden_def(sepol_context_create) 151 152 /* Deep copy clone */ 153 int sepol_context_clone(sepol_handle_t * handle, 154 const sepol_context_t * con, sepol_context_t ** con_ptr) 155 { 156 157 sepol_context_t *new_con = NULL; 158 159 if (!con) { 160 *con_ptr = NULL; 161 return 0; 162 } 163 164 if (sepol_context_create(handle, &new_con) < 0) 165 goto err; 166 167 if (!(new_con->user = strdup(con->user))) 168 goto omem; 169 170 if (!(new_con->role = strdup(con->role))) 171 goto omem; 172 173 if (!(new_con->type = strdup(con->type))) 174 goto omem; 175 176 if (con->mls && !(new_con->mls = strdup(con->mls))) 177 goto omem; 178 179 *con_ptr = new_con; 180 return STATUS_SUCCESS; 181 182 omem: 183 ERR(handle, "out of memory"); 184 185 err: 186 ERR(handle, "could not clone context record"); 187 sepol_context_free(new_con); 188 return STATUS_ERR; 189 } 190 191 hidden_def(sepol_context_clone) 192 193 /* Destroy */ 194 void sepol_context_free(sepol_context_t * con) 195 { 196 197 if (!con) 198 return; 199 200 free(con->user); 201 free(con->role); 202 free(con->type); 203 free(con->mls); 204 free(con); 205 } 206 207 hidden_def(sepol_context_free) 208 209 int sepol_context_from_string(sepol_handle_t * handle, 210 const char *str, sepol_context_t ** con) 211 { 212 213 char *tmp = NULL, *low, *high; 214 sepol_context_t *tmp_con = NULL; 215 216 if (!strcmp(str, "<<none>>")) { 217 *con = NULL; 218 return STATUS_SUCCESS; 219 } 220 221 if (sepol_context_create(handle, &tmp_con) < 0) 222 goto err; 223 224 /* Working copy context */ 225 tmp = strdup(str); 226 if (!tmp) { 227 ERR(handle, "out of memory"); 228 goto err; 229 } 230 low = tmp; 231 232 /* Then, break it into its components */ 233 234 /* User */ 235 if (!(high = strchr(low, ':'))) 236 goto mcontext; 237 else 238 *high++ = '\0'; 239 if (sepol_context_set_user(handle, tmp_con, low) < 0) 240 goto err; 241 low = high; 242 243 /* Role */ 244 if (!(high = strchr(low, ':'))) 245 goto mcontext; 246 else 247 *high++ = '\0'; 248 if (sepol_context_set_role(handle, tmp_con, low) < 0) 249 goto err; 250 low = high; 251 252 /* Type, and possibly MLS */ 253 if (!(high = strchr(low, ':'))) { 254 if (sepol_context_set_type(handle, tmp_con, low) < 0) 255 goto err; 256 } else { 257 *high++ = '\0'; 258 if (sepol_context_set_type(handle, tmp_con, low) < 0) 259 goto err; 260 low = high; 261 if (sepol_context_set_mls(handle, tmp_con, low) < 0) 262 goto err; 263 } 264 265 free(tmp); 266 *con = tmp_con; 267 268 return STATUS_SUCCESS; 269 270 mcontext: 271 errno = EINVAL; 272 ERR(handle, "malformed context \"%s\"", str); 273 274 err: 275 ERR(handle, "could not construct context from string"); 276 free(tmp); 277 sepol_context_free(tmp_con); 278 return STATUS_ERR; 279 } 280 281 hidden_def(sepol_context_from_string) 282 283 static inline int safe_sum(size_t *sum, const size_t augends[], const size_t cnt) { 284 285 size_t a, i; 286 287 *sum = 0; 288 for(i=0; i < cnt; i++) { 289 /* sum should not be smaller than the addend */ 290 a = augends[i]; 291 *sum += a; 292 if (*sum < a) { 293 return i; 294 } 295 } 296 297 return 0; 298 } 299 300 int sepol_context_to_string(sepol_handle_t * handle, 301 const sepol_context_t * con, char **str_ptr) 302 { 303 304 int rc; 305 char *str = NULL; 306 size_t total_sz, err; 307 const size_t sizes[] = { 308 strlen(con->user), /* user length */ 309 strlen(con->role), /* role length */ 310 strlen(con->type), /* type length */ 311 (con->mls) ? strlen(con->mls) : 0, /* mls length */ 312 ((con->mls) ? 3 : 2) + 1 /* mls has extra ":" also null byte */ 313 }; 314 315 err = safe_sum(&total_sz, sizes, ARRAY_SIZE(sizes)); 316 if (err) { 317 ERR(handle, "invalid size, overflow at position: %zu", err); 318 goto err; 319 } 320 321 str = (char *)malloc(total_sz); 322 if (!str) { 323 ERR(handle, "out of memory"); 324 goto err; 325 } 326 if (con->mls) { 327 rc = snprintf(str, total_sz, "%s:%s:%s:%s", 328 con->user, con->role, con->type, con->mls); 329 } else { 330 rc = snprintf(str, total_sz, "%s:%s:%s", 331 con->user, con->role, con->type); 332 } 333 334 /* 335 * rc is >= 0 on the size_t cast and is safe to promote 336 * to an unsigned value. 337 */ 338 if (rc < 0 || (size_t)rc >= total_sz) { 339 ERR(handle, "print error"); 340 goto err; 341 } 342 343 *str_ptr = str; 344 return STATUS_SUCCESS; 345 346 err: 347 ERR(handle, "could not convert context to string"); 348 free(str); 349 return STATUS_ERR; 350 } 351