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