mirror of
https://github.com/apache/nuttx-apps.git
synced 2026-08-01 20:29:00 +00:00
nshlib: Add su, id, and whoami identity commands
Add NSH commands for switching effective credentials and inspecting session identity. Update login and prompt to reflect effective user. Signed-off-by: Abhishek Mishra <mishra.abhishek2808@gmail.com>
This commit is contained in:
parent
83150e22c9
commit
78ccf6a7e1
11 changed files with 625 additions and 2 deletions
|
|
@ -42,6 +42,10 @@ if(CONFIG_NSH_LIBRARY)
|
|||
nsh_syscmds.c
|
||||
nsh_dbgcmds.c)
|
||||
|
||||
if(CONFIG_SCHED_USER_IDENTITY)
|
||||
list(APPEND CSRCS nsh_identity.c)
|
||||
endif()
|
||||
|
||||
list(APPEND CSRCS nsh_session.c)
|
||||
|
||||
if(CONFIG_NSH_CONSOLE_LOGIN)
|
||||
|
|
|
|||
|
|
@ -69,6 +69,24 @@ config NSH_PROMPT_STRING
|
|||
Provide the shell prompt string with size limit NSH_PROMPT_MAX.
|
||||
default is "nsh> ".
|
||||
|
||||
config NSH_PROMPT_STRING_ROOT
|
||||
string "Prompt string for effective root (euid=0)"
|
||||
default ""
|
||||
depends on SCHED_USER_IDENTITY
|
||||
---help---
|
||||
If non-empty, NSH uses this prompt when the effective UID is zero.
|
||||
If empty, the prompt from NSH_PROMPT_STRING (or ENV/HOSTNAME) is used.
|
||||
Set explicitly for multi-user shells (for example, "nsh# ").
|
||||
|
||||
config NSH_PROMPT_STRING_USER
|
||||
string "Prompt string for non-root effective UID"
|
||||
default ""
|
||||
depends on SCHED_USER_IDENTITY
|
||||
---help---
|
||||
If non-empty, NSH uses this prompt when the effective UID is non-zero.
|
||||
If empty, the prompt from NSH_PROMPT_STRING (or ENV/HOSTNAME) is used.
|
||||
Set explicitly for multi-user shells (for example, "nsh$ ").
|
||||
|
||||
config NSH_PROMPT_MAX
|
||||
int "Maximum Size of Prompt String"
|
||||
default NAME_MAX
|
||||
|
|
@ -351,6 +369,21 @@ config NSH_DISABLE_CHOWN
|
|||
default DEFAULT_SMALL
|
||||
depends on FS_PERMISSION
|
||||
|
||||
config NSH_DISABLE_SU
|
||||
bool "Disable su"
|
||||
default DEFAULT_SMALL
|
||||
depends on SCHED_USER_IDENTITY
|
||||
|
||||
config NSH_DISABLE_ID
|
||||
bool "Disable id"
|
||||
default DEFAULT_SMALL
|
||||
depends on SCHED_USER_IDENTITY
|
||||
|
||||
config NSH_DISABLE_WHOAMI
|
||||
bool "Disable whoami"
|
||||
default DEFAULT_SMALL
|
||||
depends on SCHED_USER_IDENTITY
|
||||
|
||||
config NSH_DISABLE_CP
|
||||
bool "Disable cp"
|
||||
default DEFAULT_SMALL
|
||||
|
|
@ -1259,6 +1292,19 @@ config NSH_LOGIN_FAILCOUNT
|
|||
---help---
|
||||
Number of login retry attempts.
|
||||
|
||||
config NSH_LOGIN_SETUID
|
||||
bool "Set user identity after successful login"
|
||||
default y
|
||||
depends on SCHED_USER_IDENTITY
|
||||
---help---
|
||||
After a successful NSH login, look up the authenticated user name
|
||||
in the passwd database and call setuid()/setgid() so that the shell
|
||||
session runs with that user's credentials.
|
||||
|
||||
When CONFIG_LIBC_PASSWD_FILE is enabled, any user listed in the
|
||||
passwd file may be selected. Otherwise only the built-in "root"
|
||||
account is supported.
|
||||
|
||||
config NSH_PLATFORM_CHALLENGE
|
||||
bool "Platform challenge"
|
||||
default n
|
||||
|
|
|
|||
|
|
@ -28,6 +28,10 @@ CSRCS = nsh_init.c nsh_parse.c nsh_console.c nsh_script.c nsh_system.c
|
|||
CSRCS += nsh_command.c nsh_fscmds.c nsh_proccmds.c nsh_mmcmds.c
|
||||
CSRCS += nsh_timcmds.c nsh_envcmds.c nsh_syscmds.c nsh_dbgcmds.c nsh_prompt.c
|
||||
|
||||
ifeq ($(CONFIG_SCHED_USER_IDENTITY),y)
|
||||
CSRCS += nsh_identity.c
|
||||
endif
|
||||
|
||||
CSRCS += nsh_session.c
|
||||
ifeq ($(CONFIG_NSH_CONSOLE_LOGIN),y)
|
||||
CSRCS += nsh_login.c
|
||||
|
|
|
|||
13
nshlib/nsh.h
13
nshlib/nsh.h
|
|
@ -750,6 +750,7 @@ extern const char g_userprompt[];
|
|||
extern const char g_passwordprompt[];
|
||||
extern const char g_loginsuccess[];
|
||||
extern const char g_badcredentials[];
|
||||
extern const char g_badidentity[];
|
||||
extern const char g_loginfailure[];
|
||||
#endif
|
||||
extern const char g_fmtsyntax[];
|
||||
|
|
@ -969,6 +970,18 @@ int cmd_irqinfo(FAR struct nsh_vtbl_s *vtbl, int argc, FAR char **argv);
|
|||
#if defined(CONFIG_FS_PERMISSION) && !defined(CONFIG_NSH_DISABLE_CHOWN)
|
||||
int cmd_chown(FAR struct nsh_vtbl_s *vtbl, int argc, FAR char **argv);
|
||||
#endif
|
||||
#ifdef CONFIG_SCHED_USER_IDENTITY
|
||||
int nsh_setuser_identity(FAR const char *username);
|
||||
# ifndef CONFIG_NSH_DISABLE_SU
|
||||
int cmd_su(FAR struct nsh_vtbl_s *vtbl, int argc, FAR char **argv);
|
||||
# endif
|
||||
# ifndef CONFIG_NSH_DISABLE_ID
|
||||
int cmd_id(FAR struct nsh_vtbl_s *vtbl, int argc, FAR char **argv);
|
||||
# endif
|
||||
# ifndef CONFIG_NSH_DISABLE_WHOAMI
|
||||
int cmd_whoami(FAR struct nsh_vtbl_s *vtbl, int argc, FAR char **argv);
|
||||
# endif
|
||||
#endif
|
||||
#ifndef CONFIG_NSH_DISABLE_CP
|
||||
int cmd_cp(FAR struct nsh_vtbl_s *vtbl, int argc, FAR char **argv);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -256,6 +256,10 @@ static const struct cmdmap_s g_cmdmap[] =
|
|||
CMD_MAP("free", cmd_free, 1, 1, NULL),
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_SCHED_USER_IDENTITY) && !defined(CONFIG_NSH_DISABLE_ID)
|
||||
CMD_MAP("id", cmd_id, 1, 1, NULL),
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_DEBUG_MM
|
||||
# ifndef CONFIG_NSH_DISABLE_MEMDUMP
|
||||
CMD_MAP("memdump", cmd_memdump,
|
||||
|
|
@ -571,6 +575,10 @@ static const struct cmdmap_s g_cmdmap[] =
|
|||
#endif
|
||||
#endif /* CONFIG_NSH_DISABLE_SET */
|
||||
|
||||
#if defined(CONFIG_SCHED_USER_IDENTITY) && !defined(CONFIG_NSH_DISABLE_SU)
|
||||
CMD_MAP("su", cmd_su, 1, 2, "[<username>]"),
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_NSH_DISABLE_SHUTDOWN
|
||||
#if defined(CONFIG_BOARDCTL_POWEROFF) && defined(CONFIG_BOARDCTL_RESET)
|
||||
CMD_MAP("shutdown", cmd_shutdown, 1, 2, "[--reboot]"),
|
||||
|
|
@ -635,6 +643,10 @@ static const struct cmdmap_s g_cmdmap[] =
|
|||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_SCHED_USER_IDENTITY) && !defined(CONFIG_NSH_DISABLE_WHOAMI)
|
||||
CMD_MAP("whoami", cmd_whoami, 1, 1, NULL),
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_NSH_DISABLE_UNAME
|
||||
# ifdef CONFIG_NET
|
||||
CMD_MAP("uname", cmd_uname, 1, 7, "[-a | -imnoprsv]"),
|
||||
|
|
|
|||
|
|
@ -45,6 +45,13 @@
|
|||
#include <errno.h>
|
||||
#include <nuttx/debug.h>
|
||||
|
||||
#ifdef CONFIG_LIBC_PASSWD_FILE
|
||||
# include <pwd.h>
|
||||
#endif
|
||||
#ifdef CONFIG_LIBC_GROUP_FILE
|
||||
# include <grp.h>
|
||||
#endif
|
||||
|
||||
#include "nsh.h"
|
||||
|
||||
#if !defined(CONFIG_DISABLE_MOUNTPOINT)
|
||||
|
|
@ -340,6 +347,44 @@ static inline int ls_specialdir(FAR const char *dir)
|
|||
|
||||
return (strcmp(dir, ".") == 0 || strcmp(dir, "..") == 0);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SCHED_USER_IDENTITY
|
||||
/****************************************************************************
|
||||
* Name: nsh_ls_printowner
|
||||
****************************************************************************/
|
||||
|
||||
static void nsh_ls_printowner(FAR struct nsh_vtbl_s *vtbl, uid_t uid,
|
||||
gid_t gid)
|
||||
{
|
||||
#ifdef CONFIG_LIBC_PASSWD_FILE
|
||||
FAR struct passwd *pwd;
|
||||
|
||||
pwd = getpwuid(uid);
|
||||
if (pwd != NULL && pwd->pw_name != NULL)
|
||||
{
|
||||
nsh_output(vtbl, "%8s", pwd->pw_name);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
nsh_output(vtbl, "%8d", (int)uid);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_LIBC_GROUP_FILE
|
||||
FAR struct group *grp;
|
||||
|
||||
grp = getgrgid(gid);
|
||||
if (grp != NULL && grp->gr_name != NULL)
|
||||
{
|
||||
nsh_output(vtbl, "%8s", grp->gr_name);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
nsh_output(vtbl, "%8d", (int)gid);
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_SCHED_USER_IDENTITY */
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
|
|
@ -511,8 +556,7 @@ static int ls_handler(FAR struct nsh_vtbl_s *vtbl, FAR const char *dirpath,
|
|||
#ifdef CONFIG_SCHED_USER_IDENTITY
|
||||
if ((lsflags & LSFLAGS_UID_GID) != 0)
|
||||
{
|
||||
nsh_output(vtbl, "%8d", buf.st_uid);
|
||||
nsh_output(vtbl, "%8d", buf.st_gid);
|
||||
nsh_ls_printowner(vtbl, buf.st_uid, buf.st_gid);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
|||
453
nshlib/nsh_identity.c
Normal file
453
nshlib/nsh_identity.c
Normal file
|
|
@ -0,0 +1,453 @@
|
|||
/****************************************************************************
|
||||
* apps/nshlib/nsh_identity.c
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <pwd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <termios.h>
|
||||
|
||||
#ifdef CONFIG_NSH_CLE
|
||||
# include "system/cle.h"
|
||||
#else
|
||||
# include "system/readline.h"
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NSH_LOGIN_PASSWD
|
||||
# include "fsutils/passwd.h"
|
||||
#endif
|
||||
|
||||
#include "nshlib/nshlib.h"
|
||||
#include "nsh.h"
|
||||
#include "nsh_console.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_is_privileged
|
||||
*
|
||||
* Description:
|
||||
* Return true if the caller has root privileges (effective UID or GID is
|
||||
* zero). NuttX does not support supplementary groups; membership in the
|
||||
* root group is indicated by a primary GID of zero.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static bool nsh_is_privileged(void)
|
||||
{
|
||||
return geteuid() == 0 || getegid() == 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_LIBC_PASSWD_FILE
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_lookup_user
|
||||
*
|
||||
* Description:
|
||||
* Look up a passwd entry by name using re-entrant libc helpers.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int nsh_lookup_user(FAR const char *username, uid_t *uid, gid_t *gid)
|
||||
{
|
||||
struct passwd pwd;
|
||||
struct passwd *result;
|
||||
char buf[CONFIG_LIBC_PASSWD_LINESIZE];
|
||||
int ret;
|
||||
|
||||
ret = getpwnam_r(username, &pwd, buf, sizeof(buf), &result);
|
||||
if (ret != 0)
|
||||
{
|
||||
return -ret;
|
||||
}
|
||||
|
||||
if (result == NULL)
|
||||
{
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
*uid = result->pw_uid;
|
||||
*gid = result->pw_gid;
|
||||
return OK;
|
||||
}
|
||||
#endif /* CONFIG_LIBC_PASSWD_FILE */
|
||||
|
||||
#ifdef CONFIG_NSH_LOGIN
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_read_password
|
||||
****************************************************************************/
|
||||
|
||||
static int nsh_read_password(FAR struct nsh_vtbl_s *vtbl,
|
||||
FAR char *password, size_t buflen)
|
||||
{
|
||||
FAR struct console_stdio_s *pstate = (FAR struct console_stdio_s *)vtbl;
|
||||
struct termios cfg;
|
||||
int ret;
|
||||
|
||||
write(OUTFD(pstate), g_passwordprompt, strlen(g_passwordprompt));
|
||||
|
||||
if (isatty(INFD(pstate)))
|
||||
{
|
||||
if (tcgetattr(INFD(pstate), &cfg) == 0)
|
||||
{
|
||||
cfg.c_lflag &= ~ECHO;
|
||||
tcsetattr(INFD(pstate), TCSANOW, &cfg);
|
||||
}
|
||||
}
|
||||
|
||||
password[0] = '\0';
|
||||
pstate->cn_line[0] = '\0';
|
||||
|
||||
#ifdef CONFIG_NSH_CLE
|
||||
ret = cle_fd(pstate->cn_line, "", LINE_MAX,
|
||||
INFD(pstate), OUTFD(pstate));
|
||||
#else
|
||||
ret = readline_fd(pstate->cn_line, LINE_MAX, INFD(pstate), -1);
|
||||
#endif
|
||||
|
||||
if (isatty(INFD(pstate)))
|
||||
{
|
||||
if (tcgetattr(INFD(pstate), &cfg) == 0)
|
||||
{
|
||||
cfg.c_lflag |= ECHO;
|
||||
tcsetattr(INFD(pstate), TCSANOW, &cfg);
|
||||
}
|
||||
}
|
||||
|
||||
if (ret > 0)
|
||||
{
|
||||
strlcpy(password, pstate->cn_line, buflen);
|
||||
write(OUTFD(pstate), "\n", 1);
|
||||
return OK;
|
||||
}
|
||||
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_verify_credentials
|
||||
****************************************************************************/
|
||||
|
||||
static bool nsh_verify_credentials(FAR const char *username,
|
||||
FAR const char *password)
|
||||
{
|
||||
#ifdef CONFIG_NSH_LOGIN_PASSWD
|
||||
return PASSWORD_VERIFY_MATCH(passwd_verify(username, password));
|
||||
#elif defined(CONFIG_NSH_LOGIN_PLATFORM)
|
||||
return PASSWORD_VERIFY_MATCH(platform_user_verify(username, password));
|
||||
#elif defined(CONFIG_NSH_LOGIN_FIXED)
|
||||
return strcmp(password, CONFIG_NSH_LOGIN_PASSWORD) == 0 &&
|
||||
strcmp(username, CONFIG_NSH_LOGIN_USERNAME) == 0;
|
||||
#else
|
||||
UNUSED(username);
|
||||
UNUSED(password);
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
#endif /* CONFIG_NSH_LOGIN */
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_switch_credentials
|
||||
*
|
||||
* Description:
|
||||
* Switch the session to the given UID/GID. NSH starts with real UID/GID
|
||||
* zero; file permission checks use the effective identity. When the real
|
||||
* UID is still zero, only the effective UID/GID are changed so that a
|
||||
* later 'su' can regain root via seteuid(0) after password verification.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int nsh_switch_credentials(uid_t uid, gid_t gid)
|
||||
{
|
||||
if (getuid() == 0)
|
||||
{
|
||||
if (geteuid() != 0 || getegid() != 0)
|
||||
{
|
||||
if (seteuid(0) != 0 || setegid(0) != 0)
|
||||
{
|
||||
return -errno;
|
||||
}
|
||||
}
|
||||
|
||||
if (seteuid(uid) != 0 || setegid(gid) != 0)
|
||||
{
|
||||
return -errno;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
if (setuid(uid) != 0 || setgid(gid) != 0)
|
||||
{
|
||||
return -errno;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_setuser_identity
|
||||
*
|
||||
* Description:
|
||||
* Look up 'username' in the passwd database and set the calling task's
|
||||
* session identity. When NSH still has real UID zero, only the effective
|
||||
* UID/GID are updated so that 'su' can switch users later.
|
||||
*
|
||||
* Input Parameters:
|
||||
* username - Login name to assume
|
||||
*
|
||||
* Returned Value:
|
||||
* OK on success; negated errno on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int nsh_setuser_identity(FAR const char *username)
|
||||
{
|
||||
#ifdef CONFIG_LIBC_PASSWD_FILE
|
||||
FAR struct passwd *pwd;
|
||||
uid_t uid;
|
||||
gid_t gid;
|
||||
|
||||
/* getpwnam() uses libc static storage; NSH is single-threaded here. */
|
||||
|
||||
pwd = getpwnam(username);
|
||||
if (pwd == NULL)
|
||||
{
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
uid = pwd->pw_uid;
|
||||
gid = pwd->pw_gid;
|
||||
#else
|
||||
uid_t uid;
|
||||
gid_t gid;
|
||||
|
||||
if (strcmp(username, "root") != 0)
|
||||
{
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
uid = 0;
|
||||
gid = 0;
|
||||
#endif
|
||||
|
||||
return nsh_switch_credentials(uid, gid);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cmd_su
|
||||
*
|
||||
* Description:
|
||||
* su [username]
|
||||
*
|
||||
* Switch the NSH session to the credentials of 'username'. Callers with
|
||||
* root privileges (effective UID or GID zero) may switch to any user
|
||||
* without a password. Other users may switch to their own identity
|
||||
* without a password, or to another user after entering that user's
|
||||
* password.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_NSH_DISABLE_SU
|
||||
int cmd_su(FAR struct nsh_vtbl_s *vtbl, int argc, FAR char **argv)
|
||||
{
|
||||
char username_buf[48];
|
||||
FAR const char *username;
|
||||
uid_t target_uid;
|
||||
gid_t target_gid;
|
||||
int ret;
|
||||
bool need_password = false;
|
||||
|
||||
if (argc > 2)
|
||||
{
|
||||
nsh_error(vtbl, g_fmtarginvalid, argv[0]);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
if (argc == 1)
|
||||
{
|
||||
username = "root";
|
||||
}
|
||||
else
|
||||
{
|
||||
/* argv[1] points into cn_line; copy it before readline reuses that
|
||||
* buffer for the password prompt.
|
||||
*/
|
||||
|
||||
strlcpy(username_buf, argv[1], sizeof(username_buf));
|
||||
username = username_buf;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_LIBC_PASSWD_FILE
|
||||
ret = nsh_lookup_user(username, &target_uid, &target_gid);
|
||||
if (ret == -ENOENT)
|
||||
{
|
||||
nsh_error(vtbl, "su: Unknown user '%s'\n", username);
|
||||
return ERROR;
|
||||
}
|
||||
else if (ret < 0)
|
||||
{
|
||||
nsh_error(vtbl, "su: Permission denied\n");
|
||||
return ERROR;
|
||||
}
|
||||
#else
|
||||
if (strcmp(username, "root") != 0)
|
||||
{
|
||||
nsh_error(vtbl, "su: Unknown user '%s'\n", username);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
target_uid = 0;
|
||||
target_gid = 0;
|
||||
#endif
|
||||
|
||||
if (!nsh_is_privileged())
|
||||
{
|
||||
#ifdef CONFIG_LIBC_PASSWD_FILE
|
||||
if (target_uid != geteuid())
|
||||
{
|
||||
need_password = true;
|
||||
}
|
||||
#else
|
||||
need_password = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NSH_LOGIN
|
||||
if (need_password)
|
||||
{
|
||||
char password[LINE_MAX];
|
||||
|
||||
ret = nsh_read_password(vtbl, password, sizeof(password));
|
||||
if (ret < 0)
|
||||
{
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
if (!nsh_verify_credentials(username, password))
|
||||
{
|
||||
nsh_error(vtbl, "su: Authentication failure\n");
|
||||
return ERROR;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (need_password)
|
||||
{
|
||||
nsh_error(vtbl, "su: Permission denied\n");
|
||||
return ERROR;
|
||||
}
|
||||
#endif
|
||||
|
||||
ret = nsh_switch_credentials(target_uid, target_gid);
|
||||
if (ret < 0)
|
||||
{
|
||||
nsh_error(vtbl, "su: Permission denied\n");
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
nsh_update_prompt();
|
||||
return OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cmd_id
|
||||
*
|
||||
* Description:
|
||||
* Print real and effective UID/GID for the current session.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_NSH_DISABLE_ID
|
||||
int cmd_id(FAR struct nsh_vtbl_s *vtbl, int argc, FAR char **argv)
|
||||
{
|
||||
if (argc != 1)
|
||||
{
|
||||
nsh_error(vtbl, g_fmtarginvalid, argv[0]);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
nsh_output(vtbl, "uid=%d euid=%d gid=%d egid=%d\n",
|
||||
getuid(), geteuid(), getgid(), getegid());
|
||||
return OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cmd_whoami
|
||||
*
|
||||
* Description:
|
||||
* Print the user name for the effective UID.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_NSH_DISABLE_WHOAMI
|
||||
int cmd_whoami(FAR struct nsh_vtbl_s *vtbl, int argc, FAR char **argv)
|
||||
{
|
||||
uid_t euid;
|
||||
|
||||
if (argc != 1)
|
||||
{
|
||||
nsh_error(vtbl, g_fmtarginvalid, argv[0]);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
euid = geteuid();
|
||||
|
||||
#ifdef CONFIG_LIBC_PASSWD_FILE
|
||||
FAR struct passwd *pwd;
|
||||
|
||||
pwd = getpwuid(euid);
|
||||
if (pwd != NULL && pwd->pw_name != NULL)
|
||||
{
|
||||
nsh_output(vtbl, "%s\n", pwd->pw_name);
|
||||
return OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (euid == 0)
|
||||
{
|
||||
nsh_output(vtbl, "root\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
nsh_output(vtbl, "%d\n", (int)euid);
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
#endif
|
||||
|
|
@ -30,6 +30,7 @@
|
|||
#include <ctype.h>
|
||||
#include <unistd.h>
|
||||
#include <termios.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "fsutils/passwd.h"
|
||||
#ifdef CONFIG_NSH_CLE
|
||||
|
|
@ -250,6 +251,16 @@ int nsh_login(FAR struct console_stdio_s *pstate)
|
|||
#endif
|
||||
{
|
||||
write(OUTFD(pstate), g_loginsuccess, strlen(g_loginsuccess));
|
||||
|
||||
#if defined(CONFIG_NSH_LOGIN_SETUID) && defined(CONFIG_SCHED_USER_IDENTITY)
|
||||
if (nsh_setuser_identity(username) < 0)
|
||||
{
|
||||
write(OUTFD(pstate), g_badidentity, strlen(g_badidentity));
|
||||
return -1;
|
||||
}
|
||||
|
||||
nsh_update_prompt();
|
||||
#endif
|
||||
return OK;
|
||||
}
|
||||
else
|
||||
|
|
|
|||
|
|
@ -316,6 +316,7 @@ const char g_userprompt[] = "login: ";
|
|||
const char g_passwordprompt[] = "password: ";
|
||||
const char g_loginsuccess[] = "\nUser Logged-in!\n";
|
||||
const char g_badcredentials[] = "\nInvalid username or password\n";
|
||||
const char g_badidentity[] = "\nUnknown user identity\n";
|
||||
const char g_loginfailure[] = "Login failed!\n";
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -30,6 +30,10 @@
|
|||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
#ifdef CONFIG_SCHED_USER_IDENTITY
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "nsh.h"
|
||||
|
||||
/****************************************************************************
|
||||
|
|
@ -59,6 +63,10 @@ static char g_nshprompt[CONFIG_NSH_PROMPT_MAX] = CONFIG_NSH_PROMPT_STRING;
|
|||
* - non-empty NSH_PROMPT_STRING
|
||||
* - non-empty HOSTNAME and suffix
|
||||
*
|
||||
* When SCHED_USER_IDENTITY is enabled and NSH_PROMPT_STRING_ROOT or
|
||||
* NSH_PROMPT_STRING_USER are non-empty, the prompt for the current
|
||||
* effective UID replaces the value from the sources above.
|
||||
*
|
||||
* Note that suffix has higher priority when used to help clearly separate
|
||||
* prompts from command line inputs.
|
||||
*
|
||||
|
|
@ -90,6 +98,22 @@ void nsh_update_prompt(void)
|
|||
gethostname(g_nshprompt, NSH_PROMPT_SIZE);
|
||||
strcat(g_nshprompt, CONFIG_NSH_PROMPT_SUFFIX);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SCHED_USER_IDENTITY
|
||||
if (geteuid() == 0)
|
||||
{
|
||||
if (CONFIG_NSH_PROMPT_STRING_ROOT[0] != '\0')
|
||||
{
|
||||
strlcpy(g_nshprompt, CONFIG_NSH_PROMPT_STRING_ROOT,
|
||||
CONFIG_NSH_PROMPT_MAX);
|
||||
}
|
||||
}
|
||||
else if (CONFIG_NSH_PROMPT_STRING_USER[0] != '\0')
|
||||
{
|
||||
strlcpy(g_nshprompt, CONFIG_NSH_PROMPT_STRING_USER,
|
||||
CONFIG_NSH_PROMPT_MAX);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#include <ctype.h>
|
||||
#include <unistd.h>
|
||||
#include <termios.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "fsutils/passwd.h"
|
||||
|
||||
|
|
@ -255,6 +256,16 @@ int nsh_telnetlogin(FAR struct console_stdio_s *pstate)
|
|||
#endif
|
||||
{
|
||||
write(OUTFD(pstate), g_loginsuccess, strlen(g_loginsuccess));
|
||||
|
||||
#if defined(CONFIG_NSH_LOGIN_SETUID) && defined(CONFIG_SCHED_USER_IDENTITY)
|
||||
if (nsh_setuser_identity(username) < 0)
|
||||
{
|
||||
write(OUTFD(pstate), g_badidentity, strlen(g_badidentity));
|
||||
return -1;
|
||||
}
|
||||
|
||||
nsh_update_prompt();
|
||||
#endif
|
||||
return OK;
|
||||
}
|
||||
else
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue