348 lines
8.3 KiB
C
348 lines
8.3 KiB
C
|
/*
|
||
|
* Copyright (C) 2007 The Android Open Source Project
|
||
|
*
|
||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
* you may not use this file except in compliance with the License.
|
||
|
* You may obtain a copy of the License at
|
||
|
*
|
||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing, software
|
||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
* See the License for the specific language governing permissions and
|
||
|
* limitations under the License.
|
||
|
*/
|
||
|
|
||
|
#include <stdlib.h>
|
||
|
#include <stdio.h>
|
||
|
#include <string.h>
|
||
|
#undef NDEBUG
|
||
|
#include <assert.h>
|
||
|
#include "permissions.h"
|
||
|
|
||
|
static int
|
||
|
test_permission_list()
|
||
|
{
|
||
|
PermissionRequestList list;
|
||
|
int ret;
|
||
|
int numRequests;
|
||
|
|
||
|
/* Bad parameter
|
||
|
*/
|
||
|
ret = initPermissionRequestList(NULL);
|
||
|
assert(ret < 0);
|
||
|
|
||
|
/* Good parameter
|
||
|
*/
|
||
|
ret = initPermissionRequestList(&list);
|
||
|
assert(ret == 0);
|
||
|
|
||
|
/* Bad parameters
|
||
|
*/
|
||
|
ret = addPermissionRequestToList(NULL, NULL, false, 0);
|
||
|
assert(ret < 0);
|
||
|
|
||
|
ret = addPermissionRequestToList(&list, NULL, false, 0);
|
||
|
assert(ret < 0);
|
||
|
|
||
|
/* Good parameters
|
||
|
*/
|
||
|
numRequests = 0;
|
||
|
|
||
|
ret = addPermissionRequestToList(&list, "one", false, 1);
|
||
|
assert(ret == 0);
|
||
|
numRequests++;
|
||
|
|
||
|
ret = addPermissionRequestToList(&list, "two", false, 2);
|
||
|
assert(ret == 0);
|
||
|
numRequests++;
|
||
|
|
||
|
ret = addPermissionRequestToList(&list, "three", false, 3);
|
||
|
assert(ret == 0);
|
||
|
numRequests++;
|
||
|
|
||
|
ret = addPermissionRequestToList(&list, "recursive", true, 55);
|
||
|
assert(ret == 0);
|
||
|
numRequests++;
|
||
|
|
||
|
/* Validate the list
|
||
|
*/
|
||
|
assert(list.requests != NULL);
|
||
|
assert(list.numRequests == numRequests);
|
||
|
assert(list.numRequests <= list.requestsAllocated);
|
||
|
bool sawOne = false;
|
||
|
bool sawTwo = false;
|
||
|
bool sawThree = false;
|
||
|
bool sawRecursive = false;
|
||
|
int i;
|
||
|
for (i = 0; i < list.numRequests; i++) {
|
||
|
PermissionRequest *req = &list.requests[i];
|
||
|
assert(req->allowed == 0);
|
||
|
|
||
|
/* Order isn't guaranteed, so we have to switch every time.
|
||
|
*/
|
||
|
if (strcmp(req->path, "one") == 0) {
|
||
|
assert(!sawOne);
|
||
|
assert(req->requested == 1);
|
||
|
assert(!req->recursive);
|
||
|
sawOne = true;
|
||
|
} else if (strcmp(req->path, "two") == 0) {
|
||
|
assert(!sawTwo);
|
||
|
assert(req->requested == 2);
|
||
|
assert(!req->recursive);
|
||
|
sawTwo = true;
|
||
|
} else if (strcmp(req->path, "three") == 0) {
|
||
|
assert(!sawThree);
|
||
|
assert(req->requested == 3);
|
||
|
assert(!req->recursive);
|
||
|
sawThree = true;
|
||
|
} else if (strcmp(req->path, "recursive") == 0) {
|
||
|
assert(!sawRecursive);
|
||
|
assert(req->requested == 55);
|
||
|
assert(req->recursive);
|
||
|
sawRecursive = true;
|
||
|
} else {
|
||
|
assert(false);
|
||
|
}
|
||
|
}
|
||
|
assert(sawOne);
|
||
|
assert(sawTwo);
|
||
|
assert(sawThree);
|
||
|
assert(sawRecursive);
|
||
|
|
||
|
/* Smoke test the teardown
|
||
|
*/
|
||
|
freePermissionRequestListElements(&list);
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static int
|
||
|
test_permission_table()
|
||
|
{
|
||
|
int ret;
|
||
|
|
||
|
/* Test the global permissions table.
|
||
|
* Try calling functions without initializing first.
|
||
|
*/
|
||
|
ret = registerPermissionSet(0, NULL);
|
||
|
assert(ret < 0);
|
||
|
|
||
|
ret = countPermissionConflicts((PermissionRequestList *)16, false);
|
||
|
assert(ret < 0);
|
||
|
|
||
|
ret = getPermissionCount();
|
||
|
assert(ret < 0);
|
||
|
|
||
|
const Permission *p;
|
||
|
p = getPermissionAt(0);
|
||
|
assert(p == NULL);
|
||
|
|
||
|
/* Initialize.
|
||
|
*/
|
||
|
ret = permissionInit();
|
||
|
assert(ret == 0);
|
||
|
|
||
|
/* Make sure we can't initialize twice.
|
||
|
*/
|
||
|
ret = permissionInit();
|
||
|
assert(ret < 0);
|
||
|
|
||
|
/* Test the inspection functions.
|
||
|
*/
|
||
|
ret = getPermissionCount();
|
||
|
assert(ret == 0);
|
||
|
|
||
|
p = getPermissionAt(-1);
|
||
|
assert(p == NULL);
|
||
|
|
||
|
p = getPermissionAt(0);
|
||
|
assert(p == NULL);
|
||
|
|
||
|
p = getPermissionAt(1);
|
||
|
assert(p == NULL);
|
||
|
|
||
|
/* Test registerPermissionSet().
|
||
|
* Try some bad parameter values.
|
||
|
*/
|
||
|
ret = registerPermissionSet(-1, NULL);
|
||
|
assert(ret < 0);
|
||
|
|
||
|
ret = registerPermissionSet(1, NULL);
|
||
|
assert(ret < 0);
|
||
|
|
||
|
/* Register some permissions.
|
||
|
*/
|
||
|
Permission p1;
|
||
|
p1.path = "one";
|
||
|
p1.allowed = 1;
|
||
|
ret = registerPermissionSet(1, &p1);
|
||
|
assert(ret == 0);
|
||
|
ret = getPermissionCount();
|
||
|
assert(ret == 1);
|
||
|
|
||
|
Permission p2[2];
|
||
|
p2[0].path = "two";
|
||
|
p2[0].allowed = 2;
|
||
|
p2[1].path = "three";
|
||
|
p2[1].allowed = 3;
|
||
|
ret = registerPermissionSet(2, p2);
|
||
|
assert(ret == 0);
|
||
|
ret = getPermissionCount();
|
||
|
assert(ret == 3);
|
||
|
|
||
|
ret = registerPermissionSet(0, NULL);
|
||
|
assert(ret == 0);
|
||
|
ret = getPermissionCount();
|
||
|
assert(ret == 3);
|
||
|
|
||
|
p1.path = "four";
|
||
|
p1.allowed = 4;
|
||
|
ret = registerPermissionSet(1, &p1);
|
||
|
assert(ret == 0);
|
||
|
|
||
|
/* Make sure the table looks correct.
|
||
|
* Order is important; more-recent additions
|
||
|
* should appear at higher indices.
|
||
|
*/
|
||
|
ret = getPermissionCount();
|
||
|
assert(ret == 4);
|
||
|
|
||
|
int i;
|
||
|
for (i = 0; i < ret; i++) {
|
||
|
const Permission *p;
|
||
|
p = getPermissionAt(i);
|
||
|
assert(p != NULL);
|
||
|
assert(p->allowed == (unsigned int)(i + 1));
|
||
|
switch (i) {
|
||
|
case 0:
|
||
|
assert(strcmp(p->path, "one") == 0);
|
||
|
break;
|
||
|
case 1:
|
||
|
assert(strcmp(p->path, "two") == 0);
|
||
|
break;
|
||
|
case 2:
|
||
|
assert(strcmp(p->path, "three") == 0);
|
||
|
break;
|
||
|
case 3:
|
||
|
assert(strcmp(p->path, "four") == 0);
|
||
|
break;
|
||
|
default:
|
||
|
assert(!"internal error");
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
p = getPermissionAt(ret);
|
||
|
assert(p == NULL);
|
||
|
|
||
|
/* Smoke test the teardown
|
||
|
*/
|
||
|
permissionCleanup();
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static int
|
||
|
test_allowed_permissions()
|
||
|
{
|
||
|
int ret;
|
||
|
int numPerms;
|
||
|
|
||
|
/* Make sure these fail before initialization.
|
||
|
*/
|
||
|
ret = countPermissionConflicts((PermissionRequestList *)1, false);
|
||
|
assert(ret < 0);
|
||
|
|
||
|
ret = getAllowedPermissions((const char *)1, false, (unsigned int *)1);
|
||
|
assert(ret < 0);
|
||
|
|
||
|
/* Initialize.
|
||
|
*/
|
||
|
ret = permissionInit();
|
||
|
assert(ret == 0);
|
||
|
|
||
|
/* Make sure countPermissionConflicts() fails with bad parameters.
|
||
|
*/
|
||
|
ret = countPermissionConflicts(NULL, false);
|
||
|
assert(ret < 0);
|
||
|
|
||
|
/* Register a set of permissions.
|
||
|
*/
|
||
|
Permission perms[] = {
|
||
|
{ "/", PERM_NONE },
|
||
|
{ "/stat", PERM_STAT },
|
||
|
{ "/read", PERMSET_READ },
|
||
|
{ "/write", PERMSET_WRITE },
|
||
|
{ "/.stat", PERM_STAT },
|
||
|
{ "/.stat/.read", PERMSET_READ },
|
||
|
{ "/.stat/.read/.write", PERMSET_WRITE },
|
||
|
{ "/.stat/.write", PERMSET_WRITE },
|
||
|
};
|
||
|
numPerms = sizeof(perms) / sizeof(perms[0]);
|
||
|
ret = registerPermissionSet(numPerms, perms);
|
||
|
assert(ret == 0);
|
||
|
|
||
|
/* Build a permission request list.
|
||
|
*/
|
||
|
PermissionRequestList list;
|
||
|
ret = initPermissionRequestList(&list);
|
||
|
assert(ret == 0);
|
||
|
|
||
|
ret = addPermissionRequestToList(&list, "/stat", false, PERM_STAT);
|
||
|
assert(ret == 0);
|
||
|
|
||
|
ret = addPermissionRequestToList(&list, "/read", false, PERM_READ);
|
||
|
assert(ret == 0);
|
||
|
|
||
|
ret = addPermissionRequestToList(&list, "/write", false, PERM_WRITE);
|
||
|
assert(ret == 0);
|
||
|
|
||
|
//TODO: cover more cases once the permission stuff has been implemented
|
||
|
|
||
|
/* All of the requests in the list should be allowed.
|
||
|
*/
|
||
|
ret = countPermissionConflicts(&list, false);
|
||
|
assert(ret == 0);
|
||
|
|
||
|
/* Add a request that will be denied.
|
||
|
*/
|
||
|
ret = addPermissionRequestToList(&list, "/stat", false, 1<<31 | PERM_STAT);
|
||
|
assert(ret == 0);
|
||
|
|
||
|
ret = countPermissionConflicts(&list, false);
|
||
|
assert(ret == 1);
|
||
|
|
||
|
//TODO: more tests
|
||
|
|
||
|
permissionCleanup();
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int
|
||
|
test_permissions()
|
||
|
{
|
||
|
int ret;
|
||
|
|
||
|
ret = test_permission_list();
|
||
|
if (ret != 0) {
|
||
|
fprintf(stderr, "test_permission_list() failed: %d\n", ret);
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
ret = test_permission_table();
|
||
|
if (ret != 0) {
|
||
|
fprintf(stderr, "test_permission_table() failed: %d\n", ret);
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
ret = test_allowed_permissions();
|
||
|
if (ret != 0) {
|
||
|
fprintf(stderr, "test_permission_table() failed: %d\n", ret);
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|