#!/usr/bin/perl use strict; use warnings; use IO::File; use IO::Pipe; use feature 'switch'; my $call_reboot = 0; my ($current_user) = getpwuid(1000); my ($filename, $conf); $filename = '/boot/firmware/sysconf.txt'; logger('info', "Reading the system configuration settings from $filename"); $conf = read_conf($filename); if (my $pass = delete($conf->{root_password})) { my $pipe; logger('debug', 'Resetting root password'); unless (open($pipe, '|-', '/usr/sbin/chpasswd')) { my $err = $!; logger('error', "Could not run chpasswd: $err"); die $err; } $pipe->print("root:$pass"); close($pipe); $call_reboot = 1; } if (my $user_pass = delete($conf->{user_password})) { my $pipe; logger('debug', "Resetting $current_user password"); unless (open($pipe, '|-', '/usr/sbin/chpasswd')) { my $err = $!; logger('error', "Could not run chpasswd: $err"); die $err; } $pipe->print("$current_user:$user_pass"); close($pipe); system("sed -i -e 's:\\] with a one time password of \\[temppwd\\]:\\]:g' /etc/issue"); system("sed -i -e 's:\\] with a one time password of \\[temppwd\\]:\\]:g' /etc/issue.net"); $call_reboot = 1; } if (my $root_authorized_key = delete($conf->{root_authorized_key})) { my $fh; logger('debug', "Adding key to root's authorized_keys"); if(! -d "/root/.ssh") { if(!mkdir("/root/.ssh", 0700)) { my $err = sprintf("Could not create /root/.ssh directory: %s", $!); logger('error', $err); die $err; } } unless ($fh = IO::File->new('/root/.ssh/authorized_keys', 'w', 0600)) { my $err = $!; logger('error', "Could not write /root/.ssh/authorized_keys: $err"); die $err; } $fh->print($root_authorized_key); $fh->close; } if (my $user_authorized_key = delete($conf->{user_authorized_key})) { my $fh; logger('debug', "Adding key to $current_user authorized_keys"); if(! -d "/home/$current_user/.ssh") { if(!mkdir("/home/$current_user/.ssh", 0700)) { my $err = sprintf("Could not create /home/$current_user/.ssh directory: %s", $!); logger('error', $err); die $err; } } unless ($fh = IO::File->new("/home/$current_user/.ssh/authorized_keys", 'w', 0600)) { my $err = $!; logger('error', "Could not write /home/$current_user/.ssh/authorized_keys: $err"); die $err; } $fh->print($user_authorized_key); $fh->close; my $user = 1000; my $group = 1000; system("chown -R $user:$group /home/$current_user/.ssh/"); } if (my $new_user_name = delete($conf->{user_name})) { logger('debug', "Changing $current_user to $new_user_name"); system("usermod --login $new_user_name --home /home/$new_user_name --move-home $current_user"); system("groupmod --new-name $new_user_name $current_user"); if( -f "/etc/lightdm/lightdm.conf") { system("sed -i -e 's:$current_user :$new_user_name:g' /etc/lightdm/lightdm.conf"); } } $call_reboot = 1; } if (my $iwd_psk_file = delete($conf->{iwd_psk_file})) { logger('debug', "Setting up iwd with '$iwd_psk_file'"); if( -f "/boot/firmware/services/$iwd_psk_file") { system("cp /boot/firmware/services/$iwd_psk_file /var/lib/iwd/"); system("dos2unix -q /var/lib/iwd/$iwd_psk_file"); system("systemctl restart iwd.service"); } } if (my $hostapd_file = delete($conf->{hostapd_file})) { logger('debug', "Setting up hostapd with '$hostapd_file'"); if( -f "/boot/firmware/services/$hostapd_file") { system("cp /boot/firmware/services/$hostapd_file /etc/hostapd/SoftAp0.conf"); system("dos2unix -q /etc/hostapd/SoftAp0.conf"); system("systemctl restart hostapd\@SoftAp0.service"); } } if (my $name = delete($conf->{hostname})) { my $fh; logger('debug', "Setting hostname to '$name'"); unless ($fh = IO::File->new('/etc/hostname', 'w')) { my $err = $!; logger('error', "Could not write hostname '$name': $err"); die $err; } $fh->print($name); $fh->close; system('hostname', '--file', '/etc/hostname'); my $fha; logger('debug', "Adding '$name' to /etc/hosts"); unless ($fha = IO::File->new('/etc/hosts', 'w')) { my $err = $!; logger('error', "Could not write to /etc/hosts '$name': $err"); die $err; } $fha->print("127.0.0.1 localhost\n"); $fha->print("127.0.1.1 ", $name, ".localdomain ", $name, "\n"); $fha->print("\n"); $fha->print("# The following lines are desirable for IPv6 capable hosts\n"); $fha->print("::1 localhost ip6-localhost ip6-loopback\n"); $fha->print("ff02::1 ip6-allnodes\n"); $fha->print("ff02::2 ip6-allrouters\n"); $fha->close; $call_reboot = 1; } if (my $legacy_rndis_support = delete($conf->{legacy_rndis_support})) { logger('debug', "Enabling Legacy RNDIS support"); if( -f "/etc/default/bb-boot") { system("sed -i -e 's:USB_RNDIS_DISABLED=yes:#USB_RNDIS_DISABLED=yes:g' /etc/default/bb-boot"); $call_reboot = 1; } } rewrite_conf_file($filename, $conf); if ($call_reboot) { system("systemctl reboot"); } exit 0; sub read_conf { my ($file, $conf, $fh); $file = shift; $conf = {}; unless ($fh = IO::File->new($filename, 'r')) { my $err = $!; logger('error', "Could not read from configuration file '$filename': $err"); # Not finding the config file is not fatal: there is just # nothing to configure! return $conf; } while (my $line = $fh->getline) { my ($key, $value); # Allow for comments, and properly ignore them $line =~ s/#.+//; if ( ($key, $value) = ($line =~ m/^\s*([^=]+)\s*=\s*(.*)\s*$/)) { $key = lc($key); if (exists($conf->{$key})) { logger('warn', "Repeated configuration key: $key. " . "Overwriting with new value ($value)"); } $conf->{$key} = $value; } } $fh->close; return $conf; } sub logger { my ($prio, $msg) = @_; system('logger', '-p', "daemon.$prio", '-t', 'bbbio-set-sysconf', $msg); } sub rewrite_conf_file { my ($filename, $conf) = @_; my $fh; unless ($fh = IO::File->new($filename, 'w')) { my $err = $!; logger('error', "Could not write to configuration file '$filename': $err"); die $err; } $fh->print( q(# This file will be automatically evaluated and installed at next boot # time, and regenerated (to avoid leaking passwords and such information). # # To force it to be evaluated immediately, you can run (as root): # # /usr/sbin/bbbio-set-sysconf # # You can disable the file evaluation by disabling the bbbio-set-sysconf # service in systemd: # # systemctl disable bbbio-set-sysconf # # Comments (all portions of a line following a '#' character) are # ignored. This file is read line by line. Valid # configuration lines are of the form 'key=value'. Whitespace around # 'key' and 'value' is ignored. This file will be _regenerated_ every # time it is evaluated. # # We follow the convention to indent with one space comments, and # leave no space to indicate the line is an example that could be # uncommented. # user_name - Set a user name for the user (1000) #user_name=beagle # user_password - Set a password for user (1000) #user_password=FooBar # user_authorized_key - Set an authorized key for a user (1000) ssh login #user_authorized_key= # iwd_psk_file - Set a configuration for iwd https://wiki.archlinux.org/title/iwd #iwd_psk_file= # hostapd_file - Set a configuration for hostapd https://wiki.gentoo.org/wiki/Hostapd #hostapd_file=SoftAp0.conf # hostname - Set the system hostname. #hostname=BeagleBone )); if (scalar keys %$conf) { logger('warn', 'Unprocessed keys left in $filename: ' . join(', ', sort keys %$conf)); $fh->print( q( # We found the following unhandled keys - That means, the # configuration script does not know how to handle them. Please # double-check them! )); $fh->print(join('', map {sprintf("%s=%s\n", $_, $conf->{$_})} sort keys %$conf)); } $fh->close; }