summaryrefslogtreecommitdiffstats
path: root/vtysh/vtysh_user.c
diff options
context:
space:
mode:
Diffstat (limited to 'vtysh/vtysh_user.c')
-rw-r--r--vtysh/vtysh_user.c235
1 files changed, 235 insertions, 0 deletions
diff --git a/vtysh/vtysh_user.c b/vtysh/vtysh_user.c
new file mode 100644
index 0000000..50b32de
--- /dev/null
+++ b/vtysh/vtysh_user.c
@@ -0,0 +1,235 @@
+/* User authentication for vtysh.
+ * Copyright (C) 2000 Kunihiro Ishiguro
+ *
+ * This file is part of GNU Zebra.
+ *
+ * GNU Zebra is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * GNU Zebra is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <zebra.h>
+#include <lib/version.h>
+
+#include <pwd.h>
+
+#ifdef USE_PAM
+#include <security/pam_appl.h>
+#ifdef HAVE_PAM_MISC_H
+#include <security/pam_misc.h>
+#endif
+#ifdef HAVE_OPENPAM_H
+#include <security/openpam.h>
+#endif
+#endif /* USE_PAM */
+
+#include "memory.h"
+#include "linklist.h"
+#include "command.h"
+#include "vtysh/vtysh_user.h"
+
+/*
+ * Compiler is warning about prototypes not being declared.
+ * The DEFUNSH and DEFUN macro's are messing with the
+ * compiler I believe. This is just to make it happy.
+ */
+#ifdef USE_PAM
+static int vtysh_pam(const char *);
+#endif
+int vtysh_auth(void);
+void vtysh_user_init(void);
+
+extern struct list *config_top;
+extern void config_add_line(struct list *config, const char *line);
+
+#ifdef USE_PAM
+static struct pam_conv conv = {PAM_CONV_FUNC, NULL};
+
+static int vtysh_pam(const char *user)
+{
+ int ret, second_ret;
+ pam_handle_t *pamh = NULL;
+
+ /* Start PAM. */
+ ret = pam_start(FRR_PAM_NAME, user, &conv, &pamh);
+
+ /* Is user really user? */
+ if (ret == PAM_SUCCESS)
+ ret = pam_authenticate(pamh, 0);
+
+ if (ret != PAM_SUCCESS)
+ fprintf(stderr, "vtysh_pam: Failure to initialize pam: %s(%d)",
+ pam_strerror(pamh, ret), ret);
+
+ second_ret = pam_acct_mgmt(pamh, 0);
+ if (second_ret != PAM_SUCCESS)
+ fprintf(stderr, "%s: Failed in account validation: %s(%d)",
+ __func__, pam_strerror(pamh, second_ret), second_ret);
+
+ /* close Linux-PAM */
+ second_ret = pam_end(pamh, ret);
+ if (second_ret != PAM_SUCCESS) {
+ pamh = NULL;
+ fprintf(stderr,
+ "vtysh_pam: failed to release authenticator: %s(%d)\n",
+ pam_strerror(pamh, second_ret), second_ret);
+ exit(1);
+ }
+
+ return ret == PAM_SUCCESS ? 0 : 1;
+}
+#endif /* USE_PAM */
+
+struct vtysh_user {
+ char *name;
+ uint8_t nopassword;
+};
+
+struct list *userlist;
+
+static struct vtysh_user *user_new(void)
+{
+ return XCALLOC(MTYPE_TMP, sizeof(struct vtysh_user));
+}
+
+static struct vtysh_user *user_lookup(const char *name)
+{
+ struct listnode *node, *nnode;
+ struct vtysh_user *user;
+
+ for (ALL_LIST_ELEMENTS(userlist, node, nnode, user)) {
+ if (strcmp(user->name, name) == 0)
+ return user;
+ }
+ return NULL;
+}
+
+void user_config_write(void)
+{
+ struct listnode *node, *nnode;
+ struct vtysh_user *user;
+ char line[128];
+
+ for (ALL_LIST_ELEMENTS(userlist, node, nnode, user)) {
+ if (user->nopassword) {
+ snprintf(line, sizeof(line), "username %s nopassword",
+ user->name);
+ config_add_line(config_top, line);
+ }
+ }
+}
+
+static struct vtysh_user *user_get(const char *name)
+{
+ struct vtysh_user *user;
+ user = user_lookup(name);
+ if (user)
+ return user;
+
+ user = user_new();
+ user->name = strdup(name);
+ listnode_add(userlist, user);
+
+ return user;
+}
+
+DEFUN (vtysh_banner_motd_file,
+ vtysh_banner_motd_file_cmd,
+ "banner motd file FILE",
+ "Set banner\n"
+ "Banner for motd\n"
+ "Banner from a file\n"
+ "Filename\n")
+{
+ int idx_file = 3;
+ return cmd_banner_motd_file(argv[idx_file]->arg);
+}
+
+DEFUN (vtysh_banner_motd_line,
+ vtysh_banner_motd_line_cmd,
+ "banner motd line LINE...",
+ "Set banner\n"
+ "Banner for motd\n"
+ "Banner from an input\n"
+ "Text\n")
+{
+ int idx = 0;
+ char *motd;
+
+ argv_find(argv, argc, "LINE", &idx);
+ motd = argv_concat(argv, argc, idx);
+
+ cmd_banner_motd_line(motd);
+ XFREE(MTYPE_TMP, motd);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (username_nopassword,
+ username_nopassword_cmd,
+ "username WORD nopassword",
+ "\n"
+ "\n"
+ "\n")
+{
+ int idx_word = 1;
+ struct vtysh_user *user;
+ user = user_get(argv[idx_word]->arg);
+ user->nopassword = 1;
+ return CMD_SUCCESS;
+}
+
+int vtysh_auth(void)
+{
+ struct vtysh_user *user;
+ struct passwd *passwd;
+
+ if ((passwd = getpwuid(geteuid())) == NULL) {
+ fprintf(stderr, "could not lookup user ID %d\n",
+ (int)geteuid());
+ exit(1);
+ }
+
+ user = user_lookup(passwd->pw_name);
+ if (user && user->nopassword)
+ /* Pass through */;
+ else {
+#ifdef USE_PAM
+ if (vtysh_pam(passwd->pw_name))
+ exit(0);
+#endif /* USE_PAM */
+ }
+ return 0;
+}
+
+char *vtysh_get_home(void)
+{
+ struct passwd *passwd;
+ char *homedir;
+
+ if ((homedir = getenv("HOME")) != NULL)
+ return homedir;
+
+ /* Fallback if HOME is undefined */
+ passwd = getpwuid(getuid());
+
+ return passwd ? passwd->pw_dir : NULL;
+}
+
+void vtysh_user_init(void)
+{
+ userlist = list_new();
+ install_element(CONFIG_NODE, &username_nopassword_cmd);
+ install_element(CONFIG_NODE, &vtysh_banner_motd_file_cmd);
+ install_element(CONFIG_NODE, &vtysh_banner_motd_line_cmd);
+}