mirror of
https://github.com/haiwen/ccnet-server.git
synced 2025-04-28 10:33:20 +00:00
191 lines
5.4 KiB
C
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;
|
|
}
|