Skip to content

Commit

Permalink
confd: add support for specifying login shell for ietf-system users
Browse files Browse the repository at this point in the history
 - Add /bin/clish (symlink) to /etc/shells, as well as the traditional
   /bin/{true,false} for completeness
 - Validate shell string, with fallback to /bin/bash and /bin/sh
 - Step infix-system revision, keeping old model in tree

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
  • Loading branch information
troglobit committed Jul 6, 2023
1 parent da39f93 commit c824b9b
Show file tree
Hide file tree
Showing 8 changed files with 138 additions and 14 deletions.
11 changes: 8 additions & 3 deletions board/common/post-build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,18 @@ rm -f "$TARGET_DIR/etc/os-release"

echo "Infix by KernelKit $GIT_VERSION -- $(date +"%b %e %H:%M %Z %Y")" > "$TARGET_DIR/etc/version"

# Allow pdmenu (setup) and bash to be a login shells, bash
# is added automatically when selected in menuyconfig, but
# not when BusyBox provides a symlink (for ash).
# Allow pdmenu (setup) and bash to be login shells, bash is added
# automatically when selected in menuyconfig, but not when BusyBox
# provides a symlink (for ash). The /bin/{true,false} are old UNIX
# beart means of disabling a user.
grep -qsE '^/usr/bin/pdmenu$$' "$TARGET_DIR/etc/shells" \
|| echo "/usr/bin/pdmenu" >> "$TARGET_DIR/etc/shells"
grep -qsE '^/bin/bash$$' "$TARGET_DIR/etc/shells" \
|| echo "/bin/bash" >> "$TARGET_DIR/etc/shells"
grep -qsE '^/bin/true$$' "$TARGET_DIR/etc/shells" \
|| echo "/bin/true" >> "$TARGET_DIR/etc/shells"
grep -qsE '^/bin/false$$' "$TARGET_DIR/etc/shells" \
|| echo "/bin/false" >> "$TARGET_DIR/etc/shells"

# Menuconfig support for modifying Qemu args in release tarballs
cp "$BR2_EXTERNAL_INFIX_PATH/board/common/qemu/qemu.sh" "$BINARIES_DIR/"
Expand Down
1 change: 0 additions & 1 deletion board/common/rootfs/etc/profile.d/convenience.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,5 @@ alias ipb='ip -br'
alias ipaddr='ip addr'
alias iplink='ip link'
alias bridge='bridge --color=auto'
alias cli='klish'

alias docker=podman
4 changes: 4 additions & 0 deletions board/netconf/post-build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,7 @@ if [ -L "$TARGET_DIR/var/lib/avahi-autoipd" ]; then
rm "$TARGET_DIR/var/lib/avahi-autoipd"
mkdir "$TARGET_DIR/var/lib/avahi-autoipd"
fi

# Allow clish (symlink to /usr/bin/klish) to be a login shell
grep -qsE '^//bin/clish$$' "$TARGET_DIR/etc/shells" \
|| echo "/bin/clish" >> "$TARGET_DIR/etc/shells"
1 change: 1 addition & 0 deletions board/netconf/rootfs/bin/clish
1 change: 1 addition & 0 deletions board/netconf/rootfs/etc/profile.d/alias.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
alias cli='clish'
86 changes: 77 additions & 9 deletions src/confd/src/confd/ietf-system.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include <assert.h>
#include <ctype.h>
#include <paths.h>
#include <pwd.h>
#include <sys/utsname.h>
#include <sys/sysinfo.h>
Expand Down Expand Up @@ -581,6 +582,35 @@ static int is_valid_username(const char *user)
return 1;
}

static char *sys_find_usable_shell(sr_session_ctx_t *sess, char *name)
{
char *shell = NULL;
char xpath[256];
sr_data_t *cfg;

snprintf(xpath, sizeof(xpath), XPATH_AUTH_"/user[name='%s']/infix-system:shell", name);
if (!sr_get_data(sess, xpath, 0, 0, 0, &cfg)) {
struct lyd_node *node;

if (!lyd_find_path(cfg->tree, xpath, 0, &node))
shell = (char *)lyd_get_value(node);
}

/* Verify the given shell exists (and is a login shell) */
if (!shell)
shell = LOGIN_SHELL;
else if (!whichp(shell))
shell = LOGIN_SHELL;

if (!whichp(shell))
shell = _PATH_BSHELL;

shell = strdup(shell);
sr_release_data(cfg);

return shell;
}

static int sys_del_user(char *user)
{
char *args[] = {
Expand All @@ -605,9 +635,9 @@ static int sys_del_user(char *user)
* that the full NACM applies to the user instead of the file system
* permissions that apply to the current klish.
*/
static int sys_add_new_user(char *name)
static int sys_add_new_user(sr_session_ctx_t *sess, char *name)
{
char *shell = LOGIN_SHELL;
char *shell = sys_find_usable_shell(sess, name);
char *sargs[] = {
"adduser", "-d", "-s", shell, "-S", "-G", "wheel", name, NULL
};
Expand All @@ -623,17 +653,15 @@ static int sys_add_new_user(char *name)
else
args = uargs; /* user */

if (!shell || !whichp(shell))
args[2] = "/bin/sh";

/**
* The Busybox implementation of 'adduser -d' sets the password
* to "*", which prevents new users from logging in until Augeas
* has set a password or SSH public keys have been installed.
*/
err = systemv_silent(args);
free(shell);
if (err) {
ERROR("Error creating new user \"%s\"\n", name);
ERROR("Failed creating new user \"%s\"\n", name);
return SR_ERR_SYS;
}
DEBUG("New user \"%s\" created\n", name);
Expand Down Expand Up @@ -709,6 +737,41 @@ static sr_error_t handle_sr_passwd_update(augeas *aug, sr_session_ctx_t *, struc
return SR_ERR_OK;
}

static sr_error_t handle_sr_shell_update(augeas *aug, sr_session_ctx_t *sess, struct sr_change *change)
{
sr_xpath_ctx_t state;
char *shell = NULL;
struct passwd *pw;
const char *user;
sr_val_t *val;
int err;

val = change->old ? : change->new;
assert(val);

user = sr_xpath_key_value(val->xpath, "user", "name", &state);

pw = getpwnam(user);
if (!pw) {
DEBUG("Skipping attribute for missing user (%s)", user);
err = SR_ERR_OK;
goto err;
}

shell = sys_find_usable_shell(sess, (char *)user);
if (aug_set_dynpath(aug, shell, "etc/passwd/%s/shell", user)) {
err = SR_ERR_SYS;
goto err;
}
DEBUG("Login shell updated for user %s", user);
err = SR_ERR_OK;
err:
if (shell)
free(shell);
sr_xpath_recover(&state);
return err;
}

static sr_error_t check_sr_user_update(augeas *aug, sr_session_ctx_t *, struct sr_change *change)
{
sr_xpath_ctx_t state;
Expand Down Expand Up @@ -739,14 +802,14 @@ static sr_error_t handle_sr_user_update(augeas *aug, sr_session_ctx_t *sess, str
assert(change->new);

name = sr_xpath_key_value(change->new->xpath, "user", "name", &state);
err = sys_add_new_user(name);
err = sys_add_new_user(sess, name);
if (err) {
sr_xpath_recover(&state);
return err;
}
DEBUG("User %s created\n", name);
sr_xpath_recover(&state);
break;
break;
case SR_OP_DELETED:
assert(change->old);

Expand All @@ -758,7 +821,7 @@ static sr_error_t handle_sr_user_update(augeas *aug, sr_session_ctx_t *sess, str
}
DEBUG("User %s deleted\n", name);
sr_xpath_recover(&state);
break;
break;
case SR_OP_MOVED:
case SR_OP_MODIFIED:
return SR_ERR_OK;
Expand Down Expand Up @@ -863,6 +926,11 @@ static sr_error_t change_auth_done(augeas *aug, sr_session_ctx_t *session)
if (err)
return err;

err = _sr_change_iter(aug, session, XPATH_AUTH_"/user[*]/shell",
handle_sr_shell_update);
if (err)
return err;

err = aug_save(aug);
if (err) {
ERROR("Error saving auth changes\n");
Expand Down
2 changes: 1 addition & 1 deletion src/confd/sysrepo-bootstrap.sh
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ sysrepoctl -s $SEARCH \
-i infix-if-type@2023-06-09.yang -g wheel -p 0660 \
-i infix-interfaces@2023-06-05.yang -g wheel -p 0660 \
-e vlan-filtering \
-i infix-system@2023-04-11.yang -g wheel -p 0660 \
-i infix-system@2023-07-06.yang -g wheel -p 0660 \
-I "${INIT_DATA}"
rc=$?

Expand Down
46 changes: 46 additions & 0 deletions src/confd/yang/infix-system@2023-07-06.yang
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
module infix-system {
yang-version 1.1;
namespace "urn:infix:system:ns:yang:1.0";
prefix infix-sys;

import ietf-system {
prefix sys;
}

include infix-system-software;

organization "KernelKit";
contact "kernelkit@googlegroups.com";
description "Infix augments and deviations to ietf-system.";

revision 2023-07-06 {
description "Add support for user login shell.";
reference "internal";
}

revision 2023-04-11 {
description "Initial revision.";
reference "internal";
}

augment "/sys:system" {
description "Augment of ietf-system for modifying /etc/motd.";
leaf motd {
type string;
description "Set the MotD (Message of the Day), shown after login";
}
}

augment "/sys:system/sys:authentication/sys:user" {
description "Augment of ietf-system to support setting login shell for users.";
leaf shell {
type string;
default "/bin/clish";
description "Set UNIX login shell for user, e.g., /bin/bash";
}
}

deviation "/sys:system/sys:clock/sys:timezone/sys:timezone-utc-offset/sys:timezone-utc-offset" {
deviate not-supported;
}
}

0 comments on commit c824b9b

Please sign in to comment.