|
Ørjan Malde |
d16cc0 |
/* mlogin: minimalistic login */
|
|
Ørjan Malde |
d16cc0 |
/* Copyright (c) 2019 Ørjan Malde */
|
|
Ørjan Malde |
d16cc0 |
/* Released under LGPL, see COPYRIGHT.MLOGIN */
|
|
Ørjan Malde |
d16cc0 |
|
|
Ørjan Malde |
24d238 |
#include <sys/types.h>
|
|
Ørjan Malde |
24d238 |
#include <unistd.h>
|
|
Ørjan Malde |
24d238 |
#include <stdlib.h>
|
|
Ørjan Malde |
24d238 |
#include <stdio.h>
|
|
Ørjan Malde |
24d238 |
#include <string.h>
|
|
Ørjan Malde |
24d238 |
#include <grp.h>
|
|
Ørjan Malde |
24d238 |
#include <pwd.h>
|
|
Ørjan Malde |
24d238 |
#include <errno.h>
|
|
Ørjan Malde |
24d238 |
#include <signal.h>
|
|
Ørjan Malde |
24d238 |
#ifdef __midipix__
|
|
Ørjan Malde |
24d238 |
#define IFLAG 1
|
|
Ørjan Malde |
24d238 |
#else
|
|
Ørjan Malde |
24d238 |
#define IFLAG 0
|
|
Ørjan Malde |
24d238 |
#endif
|
|
Ørjan Malde |
24d238 |
|
|
Ørjan Malde |
24d238 |
#include "login.h"
|
|
|
16ae2b |
#include "motd.h"
|
|
|
c95639 |
#include "os/os.h"
|
|
|
7ab29a |
|
|
|
c93694 |
static int do_login(struct passwd *pwd, int pflag)
|
|
|
b86465 |
{
|
|
|
7ab29a |
char * comspec;
|
|
|
7ab29a |
size_t envlen;
|
|
|
7ab29a |
char ** envp;
|
|
|
7ab29a |
char * envstrs;
|
|
|
7ab29a |
char * envptrs[8];
|
|
|
7ab29a |
char envbuff[3072];
|
|
|
7ab29a |
|
|
|
b86465 |
if(*pwd->pw_shell == '\0')
|
|
|
c93694 |
pwd->pw_shell = "/bin/sh";
|
|
|
b86465 |
|
|
|
b86465 |
if(chdir(pwd->pw_dir) < 0) {
|
|
|
aefc6a |
printf("no home directory %s!\n", pwd->pw_dir); /* handle -EPERM, -ENOMEM, -ESYMLNK */
|
|
|
b86465 |
|
|
|
b86465 |
if(chdir("/") == -1) {
|
|
|
b86465 |
printf("chdir failed with %s", strerror(errno));
|
|
|
c93694 |
return 0;
|
|
|
7ab29a |
} else {
|
|
|
7ab29a |
pwd->pw_dir = "/";
|
|
|
7ab29a |
}
|
|
|
7ab29a |
}
|
|
|
b86465 |
|
|
|
7ab29a |
if(pflag) {
|
|
|
7ab29a |
envp = environ;
|
|
|
7ab29a |
|
|
|
7ab29a |
(void)setenv("HOME", pwd->pw_dir, 1);
|
|
|
7ab29a |
(void)setenv("SHELL", pwd->pw_shell, 1);
|
|
|
c93694 |
(void)setenv("TERM", "xterm", 0); /* TODO: this is 500% incorrect */
|
|
|
7ab29a |
(void)setenv("LOGNAME", pwd->pw_name, 1);
|
|
|
7ab29a |
(void)setenv("USER", pwd->pw_name, 1);
|
|
|
7ab29a |
(void)setenv("PATH", "/local/sbin:/local/bin:/sbin:/bin", 0);
|
|
|
7ab29a |
} else {
|
|
|
7ab29a |
envlen = snprintf(envbuff,0,"HOME=%s",pwd->pw_dir) + 1;
|
|
|
7ab29a |
envlen += snprintf(envbuff,0,"SHELL=%s",pwd->pw_shell) + 1;
|
|
|
7ab29a |
envlen += snprintf(envbuff,0,"TERM=%s","xterm") + 1;
|
|
|
7ab29a |
envlen += snprintf(envbuff,0,"LOGNAME=%s",pwd->pw_name) + 1;
|
|
|
7ab29a |
envlen += snprintf(envbuff,0,"USER=%s",pwd->pw_name) + 1;
|
|
|
7ab29a |
envlen += snprintf(envbuff,0,"PATH=%s","/local/sbin:/local/bin:/sbin:/bin") + 1;
|
|
|
7ab29a |
|
|
|
7ab29a |
if ((comspec = getenv("ComSpec")) || (comspec = getenv("COMSSPEC")))
|
|
|
7ab29a |
envlen += snprintf(envbuff,0,"COMSPEC=%s",comspec) + 1;
|
|
|
7ab29a |
|
|
|
7ab29a |
if (envlen <= sizeof(envbuff)) {
|
|
|
7ab29a |
envp = envptrs;
|
|
|
7ab29a |
envstrs = envbuff;
|
|
|
7ab29a |
} else if ((envstrs = calloc(envlen,1))) {
|
|
|
7ab29a |
envp = envptrs;
|
|
|
7ab29a |
} else {
|
|
|
c93694 |
return 0;
|
|
|
7ab29a |
}
|
|
|
b86465 |
|
|
|
7ab29a |
envp[0] = envstrs;
|
|
|
7ab29a |
envstrs += sprintf(envstrs,"HOME=%s",pwd->pw_dir) + 1;
|
|
|
7ab29a |
|
|
|
7ab29a |
envp[1] = envstrs;
|
|
|
7ab29a |
envstrs += sprintf(envstrs,"SHELL=%s",pwd->pw_shell) + 1;
|
|
|
7ab29a |
|
|
|
7ab29a |
envp[2] = envstrs;
|
|
|
7ab29a |
envstrs += sprintf(envstrs,"TERM=%s","xterm") + 1;
|
|
|
7ab29a |
|
|
|
7ab29a |
envp[3] = envstrs;
|
|
|
7ab29a |
envstrs += sprintf(envstrs,"LOGNAME=%s",pwd->pw_name) + 1;
|
|
|
7ab29a |
|
|
|
7ab29a |
envp[4] = envstrs;
|
|
|
7ab29a |
envstrs += sprintf(envstrs,"USER=%s",pwd->pw_name) + 1;
|
|
|
7ab29a |
|
|
|
7ab29a |
envp[5] = envstrs;
|
|
|
7ab29a |
envstrs += sprintf(envstrs,"PATH=%s","/local/sbin:/local/bin:/sbin:/bin") + 1;
|
|
|
7ab29a |
|
|
|
7ab29a |
envp[6] = 0;
|
|
|
7ab29a |
envp[7] = 0;
|
|
|
7ab29a |
|
|
|
7ab29a |
if (comspec) {
|
|
|
7ab29a |
envp[6] = envstrs;
|
|
|
7ab29a |
envstrs += sprintf(envstrs,"COMSPEC=%s",comspec) + 1;
|
|
|
7ab29a |
}
|
|
|
7ab29a |
}
|
|
|
7ab29a |
|
|
|
7ab29a |
(void)signal(SIGTSTP, SIG_DFL);
|
|
|
7ab29a |
(void)signal(SIGQUIT, SIG_DFL);
|
|
|
7ab29a |
(void)signal(SIGINT, SIG_DFL);
|
|
|
7ab29a |
|
|
|
16ae2b |
motd();
|
|
|
16ae2b |
|
|
|
7ab29a |
execve(
|
|
|
7ab29a |
pwd->pw_shell,
|
|
|
7ab29a |
(char *[]){pwd->pw_shell,"-l",0},
|
|
|
7ab29a |
envp);
|
|
|
7ab29a |
|
|
|
c93694 |
return 0;
|
|
Ørjan Malde |
24d238 |
}
|
|
Ørjan Malde |
24d238 |
|
|
Ørjan Malde |
24d238 |
int main(int argc, char **argv)
|
|
Ørjan Malde |
24d238 |
{
|
|
|
c93694 |
struct passwd *pwd;
|
|
|
c93694 |
char *username = NULL;
|
|
|
c93694 |
int c, pflag, iflag = 0;
|
|
|
c93694 |
|
|
Ørjan Malde |
24d238 |
/* we don't want ^D etc to mess up the logic */
|
|
Ørjan Malde |
24d238 |
(void)signal(SIGTSTP, SIG_IGN);
|
|
Ørjan Malde |
24d238 |
(void)signal(SIGQUIT, SIG_IGN);
|
|
Ørjan Malde |
24d238 |
(void)signal(SIGINT, SIG_IGN);
|
|
Ørjan Malde |
24d238 |
|
|
Ørjan Malde |
24d238 |
while((c = getopt(argc, argv, "pfh:iw")) != -1)
|
|
Ørjan Malde |
24d238 |
switch(c) {
|
|
Ørjan Malde |
24d238 |
case 'p':
|
|
Ørjan Malde |
24d238 |
pflag = 1; break;
|
|
Ørjan Malde |
24d238 |
case 'f':
|
|
|
d382df |
(void)0; break; /* unused, pointless currently */
|
|
Ørjan Malde |
24d238 |
case 'h':
|
|
Ørjan Malde |
24d238 |
if(getuid()) {
|
|
Ørjan Malde |
24d238 |
exit(1);
|
|
Ørjan Malde |
24d238 |
}
|
|
Ørjan Malde |
24d238 |
break;
|
|
Ørjan Malde |
24d238 |
case 'i':
|
|
Ørjan Malde |
24d238 |
iflag = IFLAG; break;
|
|
Ørjan Malde |
24d238 |
default:
|
|
Ørjan Malde |
24d238 |
case '?':
|
|
Ørjan Malde |
24d238 |
usage();
|
|
Ørjan Malde |
24d238 |
break;
|
|
Ørjan Malde |
24d238 |
}
|
|
|
82a7c0 |
argv += optind;
|
|
Ørjan Malde |
24d238 |
|
|
|
c2d308 |
if(*argv)
|
|
Ørjan Malde |
24d238 |
username = *argv;
|
|
Ørjan Malde |
24d238 |
else {
|
|
Ørjan Malde |
24d238 |
printf("login: ");
|
|
Ørjan Malde |
24d238 |
fflush(0);
|
|
Ørjan Malde |
24d238 |
(void)scanf("%ms", &username);
|
|
Ørjan Malde |
24d238 |
}
|
|
Ørjan Malde |
24d238 |
pwd = getpwnam(username);
|
|
|
276bd5 |
|
|
|
9a3e75 |
/* guard against account probing */
|
|
|
9a3e75 |
if(!pwd) {
|
|
|
c93694 |
char *pw = getpass("Password: ");
|
|
|
b86465 |
explicit_bzero(pw, strlen(pw));
|
|
|
9a3e75 |
endpwent();
|
|
|
9a3e75 |
puts("Login incorrect.");
|
|
|
c93694 |
return 1;
|
|
|
b86465 |
}
|
|
|
b86465 |
|
|
|
9a3e75 |
/* midipix: are we spawning a shell? */
|
|
|
9a3e75 |
if(!iflag) {
|
|
|
c93694 |
char *pw = getpass("Password: ");
|
|
|
c93694 |
/* TODO: shadow and locked account support */
|
|
|
c93694 |
if(!(*pwd->pw_passwd == '\0' && !strlen(pw))) {
|
|
|
c93694 |
char *pw_encrypted = crypt(pw, pwd->pw_passwd);
|
|
|
9a3e75 |
/* if(timingsafe_memcmp(pw_encrypted, pwd->pw_passwd, strlen(pw_encrypted))) { */
|
|
|
9a3e75 |
if(memcmp(pw_encrypted, pwd->pw_passwd, strlen(pw_encrypted)) != 0) {
|
|
|
9a3e75 |
puts("Login incorrect.");
|
|
|
9a3e75 |
explicit_bzero(pw, strlen(pw));
|
|
|
c93694 |
return 1;
|
|
|
9a3e75 |
}
|
|
|
9a3e75 |
explicit_bzero(pw, strlen(pw));
|
|
|
9a3e75 |
}
|
|
|
9a3e75 |
}
|
|
|
9a3e75 |
|
|
Ørjan Malde |
24d238 |
endpwent();
|
|
Ørjan Malde |
24d238 |
|
|
|
9a3e75 |
/* authenticated; attempt to set user context and spawn user shell */
|
|
|
c95639 |
if(switch_user_context(pwd, username) == 0) {
|
|
|
b86465 |
if(!do_login(pwd, pflag)) {
|
|
|
b86465 |
puts("failed to spawn shell.");
|
|
Ørjan Malde |
24d238 |
}
|
|
Ørjan Malde |
24d238 |
}
|
|
Ørjan Malde |
24d238 |
puts("could not switch to specified user.");
|
|
|
c93694 |
|
|
|
c93694 |
return 2;
|
|
Ørjan Malde |
24d238 |
}
|
|
Ørjan Malde |
24d238 |
|
|
|
034530 |
void usage(void)
|
|
|
034530 |
{
|
|
|
d74de0 |
puts("login -p do not the destroy the environment");
|
|
|
d74de0 |
puts("login -f do not perform secondary authentication (noop)");
|
|
|
d74de0 |
puts("login -h pass remote server name to utmp (noop)");
|
|
Ørjan Malde |
24d238 |
exit(0);
|
|
Ørjan Malde |
24d238 |
}
|