#include #include #include #include #include #include #include #include #include /* axutils.h needs this... */ #include #include #include #include "node.h" long IdleTimeout = 360L; /* default to 6 mins */ long ConnTimeout = 300L; /* default to 5 mins */ int ReConnectTo = 0; int LogLevel = LOGLVL_ERROR; int EscChar = 20; /* CTRL-T */ char *Email = NULL; char *HostName = NULL; char *NodeId = NULL; char *NrPort = NULL; /* first netrom port */ char *FlexId = NULL; char *RoseId = NULL; #ifdef HAVEMOTD char *Prompt = "\n=> "; /* Prompt by IZ5AWZ */ #else char *Prompt = "\n"; #endif char *PassPrompt = "\nPassword >"; /* Prompt Password by IZ5AWZ */ static unsigned long Permissions = 0L; static unsigned long LocalNet = 0L; static unsigned long LocalMask = ~0L; static char *HiddenPorts[32] = {0}; /* * Return non-zero if `port' is a hidden port. */ int is_hidden(const char *port) { int i; for (i = 0; HiddenPorts[i] != NULL && i < 31; i++) if (!strcmp(port, HiddenPorts[i])) return 1; return 0; } /* * Return non-zero if peer is on "local" or loopback network. */ static int is_local(unsigned long peer) { return ((peer & LocalMask) == LocalNet) || ((peer & 0xff) == 127); } /* * Return non-zero if peer is on amprnet. */ static int is_ampr(unsigned long peer) { return ((peer & 0xff) == 44); } /* * Convert NOS style width to a netmask in network byte order. */ static unsigned long bits_to_mask(int bits) { return htonl(~0L << (32 - bits)); } int check_perms(int what, unsigned long peer) { if (what == PERM_TELNET) { if (is_local(peer)) { if (Permissions & PERM_TELNET_LOCAL) return 0; } else if (is_ampr(peer)) { if (Permissions & PERM_TELNET_AMPR) return 0; } else { if (Permissions & PERM_TELNET_INET) return 0; } return -1; } if ((Permissions & what) == 0) { return -1; } return 0; } /* * Read permissions file and return a password if needed or "*" if not. * If user access is denied return NULL. */ char *read_perms(struct user *up, unsigned long peer) { FILE *fp; char line[256], *argv[32], *cp; int argc, n = 0; if ((fp = fopen(CONF_NODE_PERMS_FILE, "r")) == NULL) { node_perror(CONF_NODE_PERMS_FILE, errno); return NULL; } if ((cp = strchr(up->call, '-')) != NULL) *cp = 0; while (fgets(line, 256, fp) != NULL) { n++; argc = parse_args(argv, line); if (argc == 0 || *argv[0] == '#') continue; if (argc != 5) { node_msg("Configuration error"); node_log(LOGLVL_ERROR, "Syntax error in permission file at line %d", n); break; } if (strcmp(argv[0], "*") && strcasecmp(argv[0], up->call)) continue; switch (up->ul_type) { case AF_FLEXNET: if (!strcmp(argv[1], "*")) break; if (!strcasecmp(argv[1], "flexnet")) break; continue; case AF_AX25: if (!strcmp(argv[1], "*")) break; if (!strcasecmp(argv[1], "ax25")) break; continue; case AF_NETROM: if (!strcmp(argv[1], "*")) break; if (!strcasecmp(argv[1], "netrom")) break; continue; #ifdef HAVE_ROSE case AF_ROSE: if (!strcmp(argv[1], "*")) break; if (!strcasecmp(argv[1], "rose")) break; continue; #endif case AF_INET: if (!strcmp(argv[1], "*")) break; if (!strcasecmp(argv[1], "local") && is_local(peer)) break; if (!strcasecmp(argv[1], "ampr") && is_ampr(peer)) break; if (!strcasecmp(argv[1], "inet") && !is_local(peer) && !is_ampr(peer)) break; continue; case AF_UNSPEC: if (!strcmp(argv[1], "*")) break; if (!strcasecmp(argv[1], "host")) break; continue; } if (up->ul_type == AF_AX25) { if (strcmp(argv[2], "*") && strcmp(argv[2], up->ul_name)) continue; } if (cp != NULL) *cp = '-'; if ((Permissions = strtoul(argv[4], NULL, 10)) == 0) return NULL; else return strdup(argv[3]); } return NULL; } static int do_alias(int argc, char **argv) { struct cmd *new; int len = 0; if (argc < 3) return -1; if ((new = calloc(1, sizeof(struct cmd))) == NULL) { node_perror("do_alias: malloc", errno); return -2; } new->name = strdup(argv[1]); while (isupper(new->name[len])) len++; /* Ok. So they can't read... */ if (len == 0) { strupr(new->name); len = strlen(new->name); } new->len = len; new->command = strdup(argv[2]); new->type = CMD_ALIAS; insert_cmd(&Nodecmds, new); return 0; } static int do_loglevel(int argc, char **argv) { if (argc < 2) return -1; LogLevel = atoi(argv[1]); return 0; } int get_escape(char *s) { int escape; char *endptr[1]; if (isdigit(*s)) { escape = strtol(s, endptr, 0); if (**endptr) return -2; else return escape; } if (strlen(s) == 1) return *s; if (strlen(s) == 2 && *s == '^') return (toupper(*++s) - 'A' + 1); if (strcasecmp(s, "off") == 0 || strcmp(s, "-1") == 0) return -1; return -2; } static int do_escapechar(int argc, char **argv) { if (argc < 2) return -1; EscChar = get_escape(argv[1]); if (EscChar < -1 || EscChar > 255) { node_msg("Configuration error"); node_log(LOGLVL_ERROR, "do_escapechar: Invalid escape character %s", argv[1]); return -2; } return 0; } static int do_idletimeout(int argc, char **argv) { if (argc < 2) return -1; IdleTimeout = atol(argv[1]); return 0; } static int do_conntimeout(int argc, char **argv) { if (argc < 2) return -1; ConnTimeout = atol(argv[1]); return 0; } static int do_hostname(int argc, char **argv) { if (argc < 2) return -1; HostName = strdup(argv[1]); return 0; } static int do_localnet(int argc, char **argv) { char *cp; if (argc < 2) return -1; if ((cp = strchr(argv[1], '/')) != NULL) { *cp = 0; LocalMask = bits_to_mask(atoi(++cp)); } LocalNet = inet_addr(argv[1]); LocalNet &= LocalMask; return 0; } static int do_reconnect(int argc, char **argv) { #ifdef HAVEMOTD if (argc < 2) return -1; if (!strcasecmp(argv[1], "on")) ReConnectTo = 1; else #endif ReConnectTo = 0; return 0; } static int do_hiddenports(int argc, char **argv) { int i; if (argc < 2) return -1; for (i = 1; i < argc && i < 31; i++) { if (ax25_config_get_dev(argv[i]) == NULL) { node_msg("Configuration error"); node_log(LOGLVL_ERROR, "do_hiddenports: invalid port %s", argv[i]); return -2; } HiddenPorts[i - 1] = strdup(argv[i]); } HiddenPorts[i - 1] = NULL; return 0; } static int do_extcmd(int argc, char **argv) { struct cmd *new; struct passwd *pw; char buf[1024]; int i, len; if (argc < 6) return -1; if ((new = calloc(1, sizeof(struct cmd))) == NULL) { node_perror("do_extcmd: malloc", errno); return -2; } new->name = strdup(argv[1]); len = 0; while (isupper(new->name[len])) len++; /* Ok. So they can't read... */ if (len == 0) { strupr(new->name); len = strlen(new->name); } new->len = len; new->flags = atoi(argv[2]); if ((pw = getpwnam(argv[3])) == NULL) { node_msg("Configuration error"); node_log(LOGLVL_ERROR, "do_extcmd: Unknown user %s", argv[3]); return -2; } new->uid = pw->pw_uid; new->gid = pw->pw_gid; new->path = strdup(argv[4]); len = 0; for (i = 0; argv[i + 5] != NULL; i++) { sprintf(&buf[len], "\"%s\" ", argv[i + 5]); len = strlen(buf); } new->command = strdup(buf); new->type = CMD_EXTERNAL; insert_cmd(&Nodecmds, new); return 0; } static int do_nodeid(int argc, char **argv) { if (User.ul_type == AF_NETROM) { if (argc < 2) return -1; NodeId = strdup(argv[1]); } else if (User.ul_type != AF_NETROM) { NodeId = strdup(argv[1]); } return 0; } static int do_flexid(int argc, char **argv) { if (argc < 2 ) return -1; FlexId = ("%s ;" , strdup(argv[1])); return 0; } static int do_roseid(int argc, char **argv) { if (argc < 2 ) return -1; RoseId = ("%s ;" , strdup(argv[1])); return 0; } static int do_prompt(int argc, char **argv) { if ((User.ul_type != AF_NETROM) || (User.ul_type != AF_INET)) { if (argc < 2) { return -1; Prompt = strdup(argv[1]); return 0; } } } static int do_passprompt(int argc, char **argv) { if (User.ul_type != AF_NETROM) { if (argc < 2) return -1; PassPrompt = strdup(argv[1]); return 0; } } static int do_nrport(int argc, char **argv) { if (argc < 2) return -1; NrPort = strdup(argv[1]); return 0; } static int do_email(int argc, char **argv) { if (argc < 2) return -1; Email = strdup(argv[1]); return 0; } int read_config(void) { struct cmd *cfg_cmds = NULL; FILE *fp; char line[256]; int ret, n = 0; add_internal_cmd(&cfg_cmds, "alias", 5, do_alias); add_internal_cmd(&cfg_cmds, "conntimeout", 11, do_conntimeout); add_internal_cmd(&cfg_cmds, "email", 5, do_email); add_internal_cmd(&cfg_cmds, "escapechar", 10, do_escapechar); add_internal_cmd(&cfg_cmds, "extcmd", 6, do_extcmd); add_internal_cmd(&cfg_cmds, "hiddenports", 11, do_hiddenports); add_internal_cmd(&cfg_cmds, "hostname", 8, do_hostname); add_internal_cmd(&cfg_cmds, "idletimeout", 11, do_idletimeout); add_internal_cmd(&cfg_cmds, "localnet", 8, do_localnet); add_internal_cmd(&cfg_cmds, "loglevel", 8, do_loglevel); add_internal_cmd(&cfg_cmds, "nodeid", 6, do_nodeid); add_internal_cmd(&cfg_cmds, "flexid", 6, do_flexid); add_internal_cmd(&cfg_cmds, "roseid", 6, do_roseid); add_internal_cmd(&cfg_cmds, "prompt", 6, do_prompt); add_internal_cmd(&cfg_cmds, "nrport", 6, do_nrport); add_internal_cmd(&cfg_cmds, "reconnect", 8, do_reconnect); add_internal_cmd(&cfg_cmds, "passprompt", 6, do_passprompt); if ((fp = fopen(CONF_NODE_FILE, "r")) == NULL) { node_perror(CONF_NODE_FILE, errno); return -1; } while (fgets(line, 256, fp) != NULL) { n++; ret = cmdparse(cfg_cmds, line); if (ret == -1) { node_msg("Configuration error"); node_log(LOGLVL_ERROR, "Syntax error in config file at line %d: %s", n, line); } if (ret < 0) { fclose(fp); return -1; } } fclose(fp); free_cmdlist(cfg_cmds); cfg_cmds = NULL; return 0; }