From 98bedb8ca0772fab1bf7ff140abdd1512ee0b344 Mon Sep 17 00:00:00 2001 From: Lisa Milne Date: Sun, 17 Dec 2023 14:11:07 +1000 Subject: [PATCH] user command to add and delete users --- clite/commands.js | 180 ------------------ clite/core.js | 100 +++++++++- clite/libs/libauth.js | 6 + clite/libs/libstd.js | 16 +- clite/libs/libstdio.js | 7 + clite/user.js | 414 +++++++++++++++++++++++++++++++++++++++++ 6 files changed, 528 insertions(+), 195 deletions(-) create mode 100644 clite/user.js diff --git a/clite/commands.js b/clite/commands.js index 94074bc..f94e74d 100644 --- a/clite/commands.js +++ b/clite/commands.js @@ -2163,186 +2163,6 @@ Options: return main(args); }); -clite.commands.load('su',function(args,env,io) { - var stdio = io.include('stdio'); - var stdlib = io.include('stdlib'); - var clite = io.include('clite'); - var auth = io.include('auth'); - var term = io.include('term'); - - var pw = null; - var preserve = true; - var shell = null; - - function help() { - stdio.printf(` -su - switch users -Usage: su [OPTION] - -Options: --? Print this help information --l Simulate a full login --m Preserve the environment --s Use the shell at -`); - } - - function changeUser() { - if (!stdlib.setgid(pw.pw_gid)) { - stdio.write(io.stderr,'internal error\n'); - io.exit(1); - return; - } - - if (!stdlib.setuid(pw.pw_uid)) { - stdio.write(io.stderr,'internal error\n'); - io.exit(1); - return; - } - - var e = null; - - if (preserve) { - e = structuredClone(env); - }else{ - e = {}; - e.USER = pw.pw_name; - e.PWD = pw.pw_dir; - e.HOME = pw.pw_dir; - e.SHELL = pw.pw_shell; - } - - if (shell == null) - shell = e.SHELL; - - var args = [shell]; - - var r = stdlib.exec(shell,args,e,io); - if (r == 0) - return; - - stdio.write(io.stderr,'internal error\n'); - - io.exit(1); - } - - function doLogin(str) { - term.ttyctrl('echo',true); - if (!auth.checkpassuid(pw.pw_uid,str)) { - stdio.printf('authentication error\n'); - io.exit(1); - return; - } - - changeUser(); - } - - function preLogin(str) { - if (str == 'no') { - io.exit(0); - return; - } - if (str != 'yes') { - cookies(); - return; - } - - if (stdlib.getuid() != 0) { - stdio.write(io.stdout,'password: '); - term.ttyctrl('echo',false); - if (!stdio.read(io.stdin,doLogin)) { - term.ttyctrl('echo',true); - stdio.write(io.stderr,'authentication error\n'); - io.exit(1); - } - return; - } - - changeUser(); - } - - function cookies() { - clite.cookienotice(); - - stdio.printf("Enter 'yes' to agree, or 'no' to cancel: "); - if (!stdio.read(io.stdin,preLogin)) { - stdio.write(io.stderr,'internal error\n'); - io.exit(1); - } - } - - function main(args) { - var user = 'root'; - var shellnext = false; - var accept = false; - for (var i=1; i -1 && uid != euid) + return false; + var egid = clite.proc.getGID(pid); + if (gid > -1 && gid != egid) + return false; + } + + if (uid > -1) + fd.node.uid = uid; + if (gid > -1) + fd.node.gid = gid; + return true; + } + clite.io.lchown = function(pid,path,uid,gid) { + var fd = getFileDesPre(pid,path,false); + if (!fd) + return false; + var euid = clite.proc.getUID(pid); + if (euid != 0) { + if (fd.node.uid != euid) + return false; + if (uid > -1 && uid != euid) + return false; + var egid = clite.proc.getGID(pid); + if (gid > -1 && gid != egid) + return false; + } + + if (uid > -1) + fd.node.uid = uid; + if (gid > -1) + fd.node.gid = gid; + return true; + } + clite.io.isatty = function(pid,fd) { return fd.node.data.istty; } clite.io.mkdir = function(pid,path,mode) { - if (typeof mode != 'number') - return false; + if (typeof mode != 'number' || mode == 0) { + mode = clite.io.modes.S_IRWXU|clite.io.modes.S_IRGRP|clite.io.modes.S_IXGRP; + } mode &= ~clite.io.modes.S_IFMT; mode |= clite.io.modes.S_IFDIR; var uid = clite.proc.getUID(pid); diff --git a/clite/libs/libauth.js b/clite/libs/libauth.js index c374e6a..7d6aecc 100644 --- a/clite/libs/libauth.js +++ b/clite/libs/libauth.js @@ -7,10 +7,16 @@ return Object.create({ setpwentry:function(pw) { return clite.user.setPWData(io.pid,pw); }, + removepw:function(uid) { + return clite.user.removePW(io.pid,uid); + }, setgrentry:function(gr) { return clite.user.setGRData(io.pid,gr); }, + removegr:function(gid) { + return clite.user.removeGR(io.pid,gid); + }, setpassuid:function(uid, pass) { return clite.user.setPasswd(io.pid,uid,pass); diff --git a/clite/libs/libstd.js b/clite/libs/libstd.js index fb01589..eea4c82 100644 --- a/clite/libs/libstd.js +++ b/clite/libs/libstd.js @@ -58,14 +58,14 @@ return Object.create({ return clite.proc.getUID(io.pid); }, setuid:function(uid) { - if (!clite.proc.setUID(io.pid,uid,false)) + if (!clite.proc.setRUID(io.pid,uid,false)) return false; - return clite.proc.setRUID(io.pid,uid,false); + return clite.proc.setUID(io.pid,uid,false); }, setreuid:function(ruid,euid) { - if (!clite.proc.setUID(io.pid,euid,false)) + if (!clite.proc.setRUID(io.pid,ruid,false)) return false; - return clite.proc.setRUID(io.pid,ruid,false); + return clite.proc.setUID(io.pid,euid,false); }, // gets the passwd file data for a user based on their uid @@ -98,14 +98,14 @@ return Object.create({ return clite.proc.getGID(io.pid); }, setgid:function(gid) { - if (!clite.proc.setGID(io.pid,gid,false)) + if (!clite.proc.setRGID(io.pid,gid,false)) return false; - return clite.proc.setRGID(io.pid,gid,false); + return clite.proc.setGID(io.pid,gid,false); }, setregid:function(rgid,egid) { - if (!clite.proc.setGID(io.pid,egid,false)) + if (!clite.proc.setRGID(io.pid,rgid,false)) return false; - return clite.proc.setRGID(io.pid,rgid,false); + return clite.proc.setGID(io.pid,egid,false); }, endgrent:function() {}, getgrent:function() { diff --git a/clite/libs/libstdio.js b/clite/libs/libstdio.js index 671b58d..2645e4e 100644 --- a/clite/libs/libstdio.js +++ b/clite/libs/libstdio.js @@ -90,6 +90,13 @@ return Object.create({ return clite.io.fchmod(io.pid,fd,mode); }, + chown:function(path,uid,gid) { + return clite.io.chown(io.pid,path,uid,gid); + }, + lchown:function(path,uid,gid) { + return clite.io.lchown(io.pid,path,uid,gid); + }, + isatty:function(fd) { return clite.io.isatty(io.pid,fd); }, diff --git a/clite/user.js b/clite/user.js new file mode 100644 index 0000000..ff68b36 --- /dev/null +++ b/clite/user.js @@ -0,0 +1,414 @@ +clite.commands.data = function() { + +clite.commands.load('su',function(args,env,io) { + var stdio = io.include('stdio'); + var stdlib = io.include('stdlib'); + var clite = io.include('clite'); + var auth = io.include('auth'); + var term = io.include('term'); + + var pw = null; + var preserve = true; + var shell = null; + + function help() { + stdio.printf(` +su - switch users +Usage: su [OPTION] + +Options: +-? Print this help information +-l Simulate a full login +-m Preserve the environment +-s Use the shell at + +-c Automatically accept cookies when switching users +`); + } + + function changeUser() { + if (!stdlib.setgid(pw.pw_gid)) { + stdio.write(io.stderr,'internal error (1)\n'); + io.exit(1); + return; + } + + if (!stdlib.setuid(pw.pw_uid)) { + stdio.write(io.stderr,'internal error (2)\n'); + io.exit(1); + return; + } + + var e = null; + + if (preserve) { + e = structuredClone(env); + }else{ + e = {}; + e.USER = pw.pw_name; + e.PWD = pw.pw_dir; + e.HOME = pw.pw_dir; + e.SHELL = pw.pw_shell; + } + + if (shell == null) + shell = e.SHELL; + + var args = [shell]; + + var r = stdlib.exec(shell,args,e,io); + if (r == 0) + return; + + stdio.write(io.stderr,'internal error (3)\n'); + + io.exit(1); + } + + function doLogin(str) { + term.ttyctrl('echo',true); + if (!auth.checkpassuid(pw.pw_uid,str)) { + stdio.printf('authentication error\n'); + io.exit(1); + return; + } + + changeUser(); + } + + function preLogin(str) { + if (str == 'no') { + io.exit(0); + return; + } + if (str != 'yes') { + cookies(); + return; + } + + if (stdlib.getuid() != 0) { + stdio.write(io.stdout,'password: '); + term.ttyctrl('echo',false); + if (!stdio.read(io.stdin,doLogin)) { + term.ttyctrl('echo',true); + stdio.write(io.stderr,'authentication error\n'); + io.exit(1); + } + return; + } + + changeUser(); + } + + function cookies() { + clite.cookienotice(); + + stdio.printf("Enter 'yes' to agree, or 'no' to cancel: "); + if (!stdio.read(io.stdin,preLogin)) { + stdio.write(io.stderr,'internal error\n'); + io.exit(1); + } + } + + function main(args) { + var user = 'root'; + var shellnext = false; + var accept = false; + for (var i=1; i [username] + +Options: +-? Print this help information +-a Add a new user account +-d Delete a user account + +-s Set the user's default shell to +-g Set the user's primary group to +`); + } + + function validateName(n) { + const char = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; + const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.-_'; + if (n.length < 2 || n.length > 12) + return false; + if (char.indexOf(n[0]) < 0) + return false; + + for (var i=0; i