Skip to content
Snippets Groups Projects
main.c 6.9 KiB
Newer Older
  • Learn to ignore specific revisions
  • Suvendhu Hansa's avatar
    Suvendhu Hansa committed
    /*
     * Copyright (C) 2024 iopsys Software Solutions AB
     *
     * This program is free software; you can redistribute it and/or modify
     * it under the terms of the GNU Lesser General Public License version 2.1
     * as published by the Free Software Foundation
     *
     *      Author: Suvendhu Hansa <suvendhu.hansa@iopsys.eu>
     */
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    #include <libubus.h>
    #include <libubox/uloop.h>
    #include <libbbfdm-ubus/bbfdm-ubus.h>
    
    #include "users.h"
    #include "helper.h"
    
    extern DM_MAP_OBJ tDynamicObj[];
    static struct bbfdm_context bbfdm_ctx = {0};
    static struct ubus_event_handler ev = {0};
    
    struct list_head user_head;
    struct list_head group_head;
    
    static void load_system_users(void)
    
    	char cmd[256] = {0};
    	char line[65] = {0};
    	g_node *node = NULL;
    
    	memset(&user_head, 0, sizeof(struct list_head));
    	INIT_LIST_HEAD(&user_head);
    
    	snprintf(cmd, sizeof(cmd), "cat /etc/passwd | cut -d: -f1");
    
    Suvendhu Hansa's avatar
    Suvendhu Hansa committed
    
    	FILE *pp = popen(cmd, "r"); // flawfinder: ignore
    	if (pp != NULL) {
    
    		while (fgets(line, sizeof(line), pp) != NULL) {
    			char name[70] = {0};
    
    Suvendhu Hansa's avatar
    Suvendhu Hansa committed
    
    			remove_new_line(line);
    
    			snprintf(name, sizeof(name), "%s", line);
    
    			if (get_section_from_config(STD_UCI_PATH, "users", "user", name) != NULL) {
    				continue;
    			}
    
    			node = (g_node *)malloc(sizeof(g_node));
    			if (node == NULL) {
    				break;
    
    
    			memset(node, 0, sizeof(g_node));
    			snprintf(node->name, sizeof(node->name), "%s", line);
    			INIT_LIST_HEAD(&node->list);
    			list_add_tail(&node->list, &user_head);
    
    Suvendhu Hansa's avatar
    Suvendhu Hansa committed
    		pclose(pp);
    	}
    }
    
    
    static void free_system_users(void)
    
    	g_node *node = NULL, *tmp = NULL;
    
    	list_for_each_entry_safe(node, tmp, &user_head, list) {
    		list_del(&node->list);
    		free(node);
    
    static void load_system_groups(void)
    
    	char cmd[256] = {0};
    
    Suvendhu Hansa's avatar
    Suvendhu Hansa committed
    	char line[65] = {0};
    
    	g_node *node = NULL;
    
    	memset(&group_head, 0, sizeof(struct list_head));
    	INIT_LIST_HEAD(&group_head);
    
    	snprintf(cmd, sizeof(cmd), "cat /etc/group | cut -d: -f1");
    
    	FILE *pp = popen(cmd, "r"); // flawfinder: ignore
    	if (pp != NULL) {
    		while (fgets(line, sizeof(line), pp) != NULL) {
    			char name[70] = {0};
    
    			remove_new_line(line);
    			snprintf(name, sizeof(name), "%s%s", GROUP_PREFIX, line);
    
    			if (get_section_from_config(STD_UCI_PATH, "users", "group", name) != NULL) {
    
    Suvendhu Hansa's avatar
    Suvendhu Hansa committed
    				continue;
    			}
    
    
    			node = (g_node *)malloc(sizeof(g_node));
    			if (node == NULL) {
    				break;
    
    			memset(node, 0, sizeof(g_node));
    			snprintf(node->name, sizeof(node->name), "%s%s", GROUP_PREFIX, line);
    			INIT_LIST_HEAD(&node->list);
    			list_add_tail(&node->list, &group_head);
    
    static void free_system_groups(void)
    
    	g_node *node = NULL, *tmp = NULL;
    
    	list_for_each_entry_safe(node, tmp, &group_head, list) {
    		list_del(&node->list);
    		free(node);
    
    Suvendhu Hansa's avatar
    Suvendhu Hansa committed
    	}
    }
    
    static void create_groups(void)
    {
    	struct uci_section *s = NULL;
    
    	usermgr_uci_init(STD_UCI_PATH);
    
    	usermgr_uci_foreach_section("users", "group", s) {
    		char *group_name = NULL;
    		const char *val = NULL;
    
    		int len = strlen(GROUP_PREFIX);
    
    		if (strncmp(s->e.name, GROUP_PREFIX, len) == 0)
    			group_name = strdup(s->e.name + len);
    		else
    			group_name = strdup(s->e.name);
    
    		val = usermgr_uci_get_value_by_section(s, "enabled");
    		bool enable = dmuci_string_to_boolean(val);
    
    		val = usermgr_uci_get_value_by_section(s, "deleted");
    		bool deleted = dmuci_string_to_boolean(val);
    
    		const char *old_name = usermgr_uci_get_value_by_section(s, "old_name");
    
    		if (deleted) {
    			del_group(group_name);
    			usermgr_uci_delete_by_section(s, NULL, NULL);
    			FREE(group_name);
    			continue;
    		}
    
    		if (strlen(old_name) != 0) {
    			del_group(old_name);
    			usermgr_uci_set_value_by_section(s, "old_name", "");
    		}
    
    		if (enable) {
    			add_group(group_name);
    		} else {
    			del_group(group_name);
    		}
    
    		FREE(group_name);
    	}
    
    	usermgr_uci_fini("users");
    }
    
    static void create_users(void)
    {
    	struct uci_section *s = NULL;
    
    	usermgr_uci_init(STD_UCI_PATH);
    
    	usermgr_uci_foreach_section("users", "user", s) {
    		const char *val = NULL;
    		char *user_name = strdup(s->e.name);
    
    		val = usermgr_uci_get_value_by_section(s, "enabled");
    		bool enable = dmuci_string_to_boolean(val);
    
    		val = usermgr_uci_get_value_by_section(s, "deleted");
    		bool deleted = dmuci_string_to_boolean(val);
    
    		const char *old_name = usermgr_uci_get_value_by_section(s, "old_name");
    		const char *member_groups = usermgr_uci_get_value_by_section(s, "member_groups");
    		const char *shell = usermgr_uci_get_value_by_section(s, "shell");
    		const char *enc_password = usermgr_uci_get_value_by_section(s, "encrypted_password");
    
    		if (deleted) {
    			del_user(user_name);
    			usermgr_uci_delete_by_section(s, NULL, NULL);
    			continue;
    		}
    
    		if (strlen(old_name) != 0) {
    			change_username(old_name, user_name);
    			usermgr_uci_set_value_by_section(s, "old_name", "");
    		}
    
    		if (!user_exist(user_name)) {
    			add_user(user_name);
    		}
    
    		if (strlen(enc_password) != 0) {
    			change_password(user_name, enc_password);
    		}
    
    
    		configure_user_shell(user_name, shell);
    		configure_user_group(user_name, member_groups);
    
    Suvendhu Hansa's avatar
    Suvendhu Hansa committed
    
    		if (enable)
    			enable_user(user_name);
    		else
    			disable_user(user_name);
    
    		FREE(user_name);
    	}
    
    	usermgr_uci_fini("users");
    }
    
    static void config_reload_cb(struct ubus_context *ctx __attribute__((unused)),
    			struct ubus_event_handler *ev __attribute__((unused)),
    			const char *type __attribute__((unused)),
    			struct blob_attr *msg __attribute__((unused)))
    {
    	create_groups();
    	create_users();
    }
    
    static int register_config_change(struct ubus_context *uctx)
    {
    	int ret;
    
    	memset(&ev, 0, sizeof(struct ubus_event_handler));
    	ev.cb = config_reload_cb;
    
    	ret = ubus_register_event_handler(uctx, &ev, "usermngr.reload");
    	if (ret)
    		return -1;
    
    	return 0;
    }
    
    
    static void usage(const char *prog)
    {
    	fprintf(stderr, "Usage: %s [options]\n", prog);
    	fprintf(stderr, "\n");
    	fprintf(stderr, "options:\n");
    	fprintf(stderr, "    -l  <0-7> Set the loglevel\n");
    
    	fprintf(stderr, "    -d <schema dm>  Display the schema data model supported by micro-service\n");
    
    	fprintf(stderr, "    -h  Displays this help\n");
    	fprintf(stderr, "\n");
    }
    
    
    Suvendhu Hansa's avatar
    Suvendhu Hansa committed
    int main(int argc, char **argv)
    {
    
    	int log_level = 7;
    
    	while ((c = getopt(argc, argv, "hdl:")) != -1) {
    
    		switch (c) {
    		case 'l':
    			log_level = (int)strtod(optarg, NULL);
    			if (log_level < 0 || log_level > 7) {
    				log_level = 7;
    			}
    			break;
    
    		case 'h':
    			usage(argv[0]);
    			exit(0);
    		default:
    			usage(argv[0]);
    			exit(0);
    		}
    	}
    
    Suvendhu Hansa's avatar
    Suvendhu Hansa committed
    
    	memset(&bbfdm_ctx, 0, sizeof(struct bbfdm_context));
    
    	bbfdm_ubus_set_service_name(&bbfdm_ctx, "usermngr");
    
    	bbfdm_ubus_set_log_level(log_level);
    
    Suvendhu Hansa's avatar
    Suvendhu Hansa committed
    	bbfdm_ubus_load_data_model(tDynamicObj);
    
    
    	if (dm_type > 0) {
    		int res = bbfdm_print_data_model_schema(&bbfdm_ctx, dm_type);
    		exit(res);
    	}
    
    	load_system_users();
    	load_system_groups();
    
    	create_groups();
    	create_users();
    
    
    Suvendhu Hansa's avatar
    Suvendhu Hansa committed
    	if (bbfdm_ubus_regiter_init(&bbfdm_ctx))
    		goto out;
    
    	if (register_config_change(&bbfdm_ctx.ubus_ctx) != 0)
    		goto out;
    
    	uloop_run();
    
    out:
    
    	free_system_users();
    	free_system_groups();
    
    Suvendhu Hansa's avatar
    Suvendhu Hansa committed
    	bbfdm_ubus_regiter_free(&bbfdm_ctx);
    	return 0;
    }