1
0
mirror of https://github.com/haiwen/ccnet-server.git synced 2025-04-28 10:33:20 +00:00
ccnet-server/net/common/perm-mgr.c
2016-08-19 13:54:34 +08:00

191 lines
5.4 KiB
C

/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
#include "common.h"
#include "peer.h"
#include "session.h"
#include "peer-mgr.h"
#include "perm-mgr.h"
#define DEBUG_FLAG CCNET_DEBUG_OTHER
#include "log.h"
/* Give an user and a service, for each role of this user:
1. find the service group,
2. use hash table 'role2groups' to find the permitted groups to this role,
3. check whether the given group in the list of groups.
*/
struct _CcnetPermManagerPriv {
GHashTable *serv2group; /* service to group map */
GHashTable *role2groups; /* role -> list of groups */
GList *anonymous_groups; /* permitted groups to anonymous user. */
};
struct ServiceGroup {
const char *service;
const char *group;
};
/* only service that can be accessed from network peers should list here,
* service accessed only by local peers do not need be list here. */
struct ServiceGroup service_groups[] = {
{ "put-pubinfo", "basic" },
{ "put-user", "basic" },
{ "keepalive2", "basic" },
{ "receive-session-key", "basic" },
{ "receive-skey2", "basic" },
{ "receive-msg", "basic" },
{ "echo", "basic" },
{ "ccnet-rpcserver", "rpc-inner" },
#ifdef CCNET_SERVER
{ "recvlogin", "basic" },
{ "recvlogout", "basic" },
{ "receive-profile", "relay-service" },
#endif
{ NULL, NULL },
};
struct RolePerm {
const char *role;
const char *group;
};
typedef struct RolePermList {
GList *list;
} RolePermList;
struct RolePerm role_perms[] = {
{ "MyClient", "seafserv" },
{ "MyClient", "relay-service" },
{ "MyAdmin", "rpc-inner" },
{ "ClusterMember", "seafserv-inner" },
{ "BlockClient", "seablock" },
{ NULL, NULL },
};
CcnetPermManager *
ccnet_perm_manager_new (CcnetSession *session)
{
CcnetPermManager *mgr = g_new0 (CcnetPermManager, 1);
mgr->priv = g_new0 (CcnetPermManagerPriv, 1);
mgr->session = session;
mgr->priv->serv2group = g_hash_table_new (g_str_hash, g_str_equal);
mgr->priv->role2groups = g_hash_table_new (g_str_hash, g_str_equal);
return mgr;
}
static void populate_default_items(CcnetPermManager *mgr);
int
ccnet_perm_manager_prepare (CcnetPermManager *mgr)
{
populate_default_items (mgr);
return 0;
}
static void
populate_default_items (CcnetPermManager *mgr)
{
struct ServiceGroup *sg;
for (sg = service_groups; sg->service; sg++) {
g_hash_table_insert (mgr->priv->serv2group, g_strdup(sg->service),
g_strdup(sg->group));
}
struct RolePerm *rp;
for (rp = role_perms; rp->role; rp++) {
RolePermList *list;
list = g_hash_table_lookup (mgr->priv->role2groups, rp->role);
if (!list) {
list = g_new0(RolePermList, 1);
g_hash_table_insert (mgr->priv->role2groups, g_strdup(rp->role),
list);
}
list->list = g_list_prepend (list->list, g_strdup(rp->group));
}
}
static inline const char *
get_service_group(CcnetPermManager *mgr, const char *service)
{
return g_hash_table_lookup (mgr->priv->serv2group, service);
}
int
check_role_permission(CcnetPermManager *mgr, const char *role, const char *group)
{
RolePermList *rplist;
GList *ptr;
rplist = g_hash_table_lookup (mgr->priv->role2groups, role);
if (!rplist)
return PERM_CHECK_ERROR;
for (ptr = rplist->list; ptr; ptr = ptr->next) {
if (strcmp(ptr->data, group) == 0)
return PERM_CHECK_OK;
}
return PERM_CHECK_ERROR;
}
/* for unit test */
int
ccnet_perm_manager_check_role_permission(CcnetPermManager *mgr,
const char *role, const char *group)
{
return check_role_permission (mgr, role, group);
}
int
ccnet_perm_manager_check_permission (CcnetPermManager *mgr,
CcnetPeer *peer,
const char *req,
int req_id,
int argc, char **argv)
{
const char *group = get_service_group (mgr, req);
if (!group)
return PERM_CHECK_NOSERVICE;
if (g_strcmp0(group, "basic") == 0)
return PERM_CHECK_OK;
if (peer->is_local)
return PERM_CHECK_OK;
if (g_strcmp0(group, "inner") == 0)
return PERM_CHECK_ERROR;
if (g_strcmp0 (group, "self") == 0) {
if (g_strcmp0 (peer->id, mgr->session->base.id) == 0)
/* myself user */
return PERM_CHECK_OK;
else
return PERM_CHECK_ERROR;
}
GList *ptr;
for (ptr = peer->role_list; ptr; ptr = ptr->next) {
if (check_role_permission(mgr, ptr->data, group) == PERM_CHECK_OK)
return PERM_CHECK_OK;
}
return PERM_CHECK_ERROR;
}
int
ccnet_perm_manager_register_service (CcnetPermManager *mgr,
const char *service,
const char *group,
CcnetPeer *peer)
{
if (g_hash_table_lookup (mgr->priv->serv2group, service))
return -1;
ccnet_debug ("[perm-mgr] register service %s %s\n", service, group);
g_hash_table_insert (mgr->priv->serv2group, g_strdup(service),
g_strdup(group));
return 0;
}