mirror of
https://codeberg.org/TicklishHoneyBee/CLIte.git
synced 2026-03-11 09:04:37 +00:00
add ability to add and edit users and groups
This commit is contained in:
parent
a7f5087c7c
commit
b14fc8e13b
3 changed files with 266 additions and 14 deletions
200
clite/core.js
200
clite/core.js
|
|
@ -9,7 +9,7 @@ var clite = {
|
|||
// a list of program/command files to load
|
||||
prog:['commands.js','shell.js','vi.js'],
|
||||
// a list of library files to load
|
||||
libs:['libclite.js','libcurses.js','libstd.js','libstdio.js','libterm.js','libtime.js']
|
||||
libs:['libclite.js','libcurses.js','libstd.js','libstdio.js','libterm.js','libtime.js','libauth.js']
|
||||
},
|
||||
time:{
|
||||
sec:function() {
|
||||
|
|
@ -270,32 +270,38 @@ var clite = {
|
|||
|
||||
function defaultConfig() {
|
||||
// /etc/env contains the default environment variables
|
||||
{
|
||||
vfsapi.mkFile(0,'/etc/env');
|
||||
var n = vfsapi.getNode(0,'/etc/env');
|
||||
let n = vfsapi.getNode(0,'/etc/env');
|
||||
if (!n) {
|
||||
clite.log.write('environment failure');
|
||||
return false;
|
||||
}
|
||||
n.data.content = `
|
||||
PATH=/bin
|
||||
EDITOR=/bin/vi
|
||||
`;
|
||||
n.mode = clite.lib.modestr('-rw-r--r--');
|
||||
}
|
||||
// /etc/passwd contains user account details
|
||||
{
|
||||
vfsapi.mkFile(0,'/etc/passwd');
|
||||
var n = vfsapi.getNode(0,'/etc/passwd');
|
||||
let n = vfsapi.getNode(0,'/etc/passwd');
|
||||
if (!n) {
|
||||
clite.log.write('access config failure');
|
||||
return false;
|
||||
}
|
||||
n.data.content = `
|
||||
root:x:0:0:root:/root:/bin/sh
|
||||
root:$-7a1c0437:0:0:root:/root:/bin/sh
|
||||
guest:x:1:1:guest:/usr/home/guest:/bin/sh
|
||||
`;
|
||||
// TODO: check cookies for a local user
|
||||
n.mode = clite.lib.modestr('-rw-r--r--');
|
||||
// /etc/passwd contains user account details
|
||||
n.mode = clite.lib.modestr('-rw-------');
|
||||
}
|
||||
// /etc/group contains group details
|
||||
{
|
||||
vfsapi.mkFile(0,'/etc/group');
|
||||
var n = vfsapi.getNode(0,'/etc/group');
|
||||
let n = vfsapi.getNode(0,'/etc/group');
|
||||
if (!n) {
|
||||
clite.log.write('group config failure');
|
||||
return false;
|
||||
|
|
@ -306,9 +312,11 @@ guest:x:1:
|
|||
`;
|
||||
// TODO: check cookies for a local user
|
||||
n.mode = clite.lib.modestr('-rw-r--r--');
|
||||
}
|
||||
// /etc/greeting is displayed by the shell after login
|
||||
{
|
||||
vfsapi.mkFile(0,'/etc/greeting');
|
||||
var n = vfsapi.getNode(0,'/etc/greeting');
|
||||
let n = vfsapi.getNode(0,'/etc/greeting');
|
||||
if (!n) {
|
||||
clite.log.write('config failure');
|
||||
return false;
|
||||
|
|
@ -322,9 +330,11 @@ guest:x:1:
|
|||
\\_____|______|_____|\\__\\___|
|
||||
`;
|
||||
n.mode = clite.lib.modestr('-rw-r--r--');
|
||||
}
|
||||
// /etc/shrc shell startup file
|
||||
{
|
||||
vfsapi.mkFile(0,'/etc/shrc');
|
||||
var n = vfsapi.getNode(0,'/etc/shrc');
|
||||
let n = vfsapi.getNode(0,'/etc/shrc');
|
||||
if (!n) {
|
||||
clite.log.write('shell config failure');
|
||||
return false;
|
||||
|
|
@ -333,6 +343,7 @@ guest:x:1:
|
|||
cat /etc/greeting
|
||||
`;
|
||||
n.mode = clite.lib.modestr('-rwxr-xr-x');
|
||||
}
|
||||
}
|
||||
|
||||
function loadCommands(nextfn) {
|
||||
|
|
@ -802,6 +813,7 @@ clite.user = {
|
|||
var data = {
|
||||
users:[{
|
||||
name:'root',
|
||||
pass:'',
|
||||
uid:0,
|
||||
gid:0,
|
||||
groups:[],
|
||||
|
|
@ -831,6 +843,10 @@ clite.user = {
|
|||
}
|
||||
return null;
|
||||
}
|
||||
function saveUsers() {
|
||||
// TODO: write /etc/passwd and /etc/group
|
||||
// TODO: write all non-root and non-guest lines to cookies
|
||||
}
|
||||
function loadUsers() {
|
||||
// load in user data from /etc/passwd
|
||||
var n = vfsapi.getFile(0,'/etc/passwd');
|
||||
|
|
@ -842,7 +858,7 @@ clite.user = {
|
|||
return;
|
||||
var sects = line.split(':');
|
||||
// 0 username
|
||||
// 1 null
|
||||
// 1 password hash
|
||||
// 2 uid
|
||||
// 3 gid
|
||||
// 4 real name
|
||||
|
|
@ -858,6 +874,9 @@ clite.user = {
|
|||
}
|
||||
|
||||
udata.name = sects[0];
|
||||
udata.pass = sects[1];
|
||||
if (udata.pass[0] == '$')
|
||||
udata.pass = udata.pass.substring(1);
|
||||
udata.uid = parseInt(sects[2]);
|
||||
udata.gid = parseInt(sects[3]);
|
||||
udata.groups = [];
|
||||
|
|
@ -971,6 +990,76 @@ cat -l /usr/share/introduction
|
|||
pw_shell:udata.env.SHELL // Program to use as shell.
|
||||
});
|
||||
}
|
||||
clite.user.getPWDataInd = function(i) {
|
||||
if (i >= data.user.length)
|
||||
return null;
|
||||
|
||||
var udata = data.users[i];
|
||||
|
||||
return Object.create({
|
||||
pw_name:udata.name, // User's login name.
|
||||
pw_uid:udata.uid, // Numerical user ID.
|
||||
pw_gid:udata.gid, // Numerical group ID.
|
||||
pw_dir:udata.env.HOME, // Initial working directory.
|
||||
pw_shell:udata.env.SHELL // Program to use as shell.
|
||||
});
|
||||
}
|
||||
clite.user.setPWData = function(pid,pw) {
|
||||
if (typeof pw.pw_name !== 'string')
|
||||
return false;
|
||||
if (typeof pw.pw_uid !== 'number')
|
||||
return false;
|
||||
if (typeof pw.pw_gid !== 'number')
|
||||
return false;
|
||||
var gr = clite.user.getGRData(pw.pw_gid);
|
||||
if (gr == null)
|
||||
return false;
|
||||
if (typeof pw.pw_dir !== 'string')
|
||||
return false;
|
||||
if (typeof pw.pw_shell !== 'string')
|
||||
return false;
|
||||
loadUsers();
|
||||
if (pw.pw_uid < 0) {
|
||||
if (clite.user.mapUserName(pw.pw_name) > -1)
|
||||
return false;
|
||||
var udata = {};
|
||||
udata.name = pw.pw_name;
|
||||
udata.pass = 'x';
|
||||
// TODO: this could cause 2 users with the same uid
|
||||
udata.uid = data.users.length;
|
||||
udata.gid = pw.pw_gid;
|
||||
udata.groups = [];
|
||||
udata.env = {};
|
||||
udata.env.HOME = pw.pw_dir;
|
||||
udata.env.SHELL = pw.pw_shell;
|
||||
udata.env.USER = udata.name;
|
||||
udata.env.PWD = udata.env.HOME;
|
||||
|
||||
data.users.push(udata);
|
||||
|
||||
saveUsers();
|
||||
loadUsers();
|
||||
return true;
|
||||
}
|
||||
var uid = clite.proc.getUID(pid);
|
||||
if (pw.pw_uid != uid && uid != 0)
|
||||
return false;
|
||||
|
||||
var udata = getUser(pw.pw_uid);
|
||||
if (!udata)
|
||||
return false;
|
||||
udata.name = pw.pw_name;
|
||||
udata.uid = pw.pw_uid;
|
||||
udata.gid = pw.pw_gid;
|
||||
udata.env.HOME = pw.pw_dir;
|
||||
udata.env.SHELL = pw.pw_shell;
|
||||
udata.env.USER = udata.name;
|
||||
udata.env.PWD = udata.env.HOME;
|
||||
|
||||
saveUsers();
|
||||
loadUsers();
|
||||
return true;
|
||||
}
|
||||
clite.user.getGRData = function(gid) {
|
||||
var gdata = getGroup(gid);
|
||||
if (!gdata)
|
||||
|
|
@ -982,6 +1071,54 @@ cat -l /usr/share/introduction
|
|||
gr_mem:gdata.users // array of member names.
|
||||
});
|
||||
}
|
||||
clite.user.getGRDataInd = function(i) {
|
||||
if (i >= data.groups.length)
|
||||
return null;
|
||||
|
||||
var gdata = data.groups[i];
|
||||
|
||||
return Object.create({
|
||||
gr_name:gdata.name, // The name of the group.
|
||||
gr_gid:gdata.gid, // Numerical group ID.
|
||||
gr_mem:gdata.users // array of member names.
|
||||
});
|
||||
}
|
||||
clite.user.setGRData = function(pid,gr) {
|
||||
if (typeof gr.gr_name !== 'string')
|
||||
return false;
|
||||
if (typeof gr.gr_gid !== 'number')
|
||||
return false;
|
||||
if (!Array.isArray(gr.gr_mem))
|
||||
return false;
|
||||
loadUsers();
|
||||
if (gr.gr_gid < 0) {
|
||||
if (clite.user.mapGroupName(gr.gr_name) > -1)
|
||||
return false;
|
||||
var gdata = {};
|
||||
gdata.name = gr.gr_name;
|
||||
// TODO: this could cause 2 groups with the same gid
|
||||
gdata.gid = data.groups.length;
|
||||
gdata.users = Array.from(gr.gr_mem);
|
||||
data.groups.push(gdata);
|
||||
saveUsers();
|
||||
loadUsers();
|
||||
|
||||
return true;
|
||||
}
|
||||
var uid = clite.proc.getUID(pid);
|
||||
if (!clite.user.checkGID(uid,gr.gr_gid) && uid != 0)
|
||||
return false;
|
||||
var gdata = getGroup(gr.gr_gid);
|
||||
if (!gdata)
|
||||
return false;
|
||||
gdata.name = gr.gr_name;
|
||||
gdata.gid = gr.gr_gid;
|
||||
gdata.users = Array.from(gr.gr_mem);
|
||||
|
||||
saveUsers();
|
||||
loadUsers();
|
||||
return true;
|
||||
}
|
||||
clite.user.mapUserName = function(name) {
|
||||
for (var i=0; i<data.users.length; i++) {
|
||||
if (data.users[i].name == name)
|
||||
|
|
@ -996,6 +1133,35 @@ cat -l /usr/share/introduction
|
|||
}
|
||||
return -1;
|
||||
}
|
||||
clite.user.setPasswd = function(pid,uid,pass) {
|
||||
var udata = getUser(uid);
|
||||
if (!udata)
|
||||
return false;
|
||||
|
||||
var puid = clite.proc.getUID(pid);
|
||||
if (puid != uid && puid != 0)
|
||||
return false;
|
||||
|
||||
var ps = pass+':'+udata.name;
|
||||
var cp = clite.lib.hash(ps);
|
||||
|
||||
udata.pass = cp;
|
||||
saveUsers();
|
||||
loadUsers();
|
||||
return true;
|
||||
}
|
||||
clite.user.checkPasswd = function(uid,pass) {
|
||||
var udata = getUser(uid);
|
||||
if (!udata)
|
||||
return false;
|
||||
|
||||
var ps = pass+':'+udata.name;
|
||||
var cp = clite.lib.hash(ps);
|
||||
|
||||
if (ps == udata.pass)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
loadUsers();
|
||||
|
||||
|
|
@ -2722,6 +2888,20 @@ clite.lib = {
|
|||
return true;
|
||||
return false;
|
||||
},
|
||||
// really basic hashing function
|
||||
hash:function(str) {
|
||||
let hash = 0;
|
||||
if (str.length == 0)
|
||||
return hash;
|
||||
|
||||
for (var i=0; i<str.length; i++) {
|
||||
let char = str.charCodeAt(i);
|
||||
hash = ((hash << 5) - hash) + char;
|
||||
hash |= 0;
|
||||
}
|
||||
|
||||
return hash;
|
||||
},
|
||||
// creates a string from a file mode (0777 -> -rwxrwxrwx)
|
||||
strmode:function(mode) {
|
||||
var str = mode.toString(8);
|
||||
|
|
|
|||
39
clite/libauth.js
Normal file
39
clite/libauth.js
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
clite.libs.data = function() {
|
||||
|
||||
clite.libs.load('libauth','auth',function(io,env) {
|
||||
|
||||
return Object.create({
|
||||
|
||||
setpwentry:function(pw) {
|
||||
return clite.user.setPWData(io.pid,pw);
|
||||
},
|
||||
|
||||
setgrentry:function(gr) {
|
||||
return clite.user.setGRData(io.pid,gr);
|
||||
},
|
||||
|
||||
setpassuid:function(uid, pass) {
|
||||
return clite.user.setPasswd(io.pid,uid,pass);
|
||||
},
|
||||
setpassnam:function(name, pass) {
|
||||
var uid = clite.user.mapUserName(name);
|
||||
if (uid < 0)
|
||||
return false;
|
||||
return clite.user.setPasswd(io.pid,uid,pass);
|
||||
},
|
||||
|
||||
checkpassuid:function(uid, pass) {
|
||||
return clite.user.checkPasswd(uid,pass);
|
||||
},
|
||||
checkpassnam:function(name, pass) {
|
||||
var uid = clite.user.mapUserName(name);
|
||||
if (uid < 0)
|
||||
return false;
|
||||
return clite.user.checkPasswd(uid,pass);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
|
@ -2,6 +2,9 @@ clite.libs.data = function() {
|
|||
|
||||
clite.libs.load('libstd','stdlib',function(io,env) {
|
||||
|
||||
var pwentind = 0;
|
||||
var grentind = 0;
|
||||
|
||||
return Object.create({
|
||||
|
||||
// returns the file name of a path /tmp/test/foo = foo
|
||||
|
|
@ -17,6 +20,10 @@ return Object.create({
|
|||
return parts.join('/');
|
||||
},
|
||||
|
||||
crypt:function(str,salt) {
|
||||
return clite.lib.hash(str.toString()+':'+salt.toString());
|
||||
},
|
||||
|
||||
// returns system info
|
||||
uname:function() {
|
||||
return Object.create({
|
||||
|
|
@ -47,8 +54,11 @@ return Object.create({
|
|||
getuid:function() {
|
||||
return clite.proc.getUID(io.pid);
|
||||
},
|
||||
setuid:function(id) {
|
||||
return clite.proc.setUID(io.pid,id,false);
|
||||
setuid:function(uid) {
|
||||
return clite.proc.setUID(io.pid,uid,false);
|
||||
},
|
||||
setreuid:function(ruid,euid) {
|
||||
return clite.proc.setGID(io.pid,euid,false);
|
||||
},
|
||||
|
||||
// gets the passwd file data for a user based on their uid
|
||||
|
|
@ -62,13 +72,36 @@ return Object.create({
|
|||
return null;
|
||||
return clite.user.getPWData(uid);
|
||||
},
|
||||
endpwent:function() {},
|
||||
getpwent:function() {
|
||||
var e = clite.user.getPWDataInd(pwentind);
|
||||
if (e !== null)
|
||||
grentind++;
|
||||
return e;
|
||||
},
|
||||
setpwent:function() {
|
||||
pwentind = 0;
|
||||
},
|
||||
|
||||
// returns the current group id
|
||||
getgid:function() {
|
||||
return clite.proc.getGID(io.pid);
|
||||
},
|
||||
setgid:function(id) {
|
||||
return clite.proc.setGID(io.pid,id,false);
|
||||
setgid:function(gid) {
|
||||
return clite.proc.setGID(io.pid,gid,false);
|
||||
},
|
||||
setregid:function(rgid,egid) {
|
||||
return clite.proc.setGID(io.pid,egid,false);
|
||||
},
|
||||
endgrent:function() {},
|
||||
getgrent:function() {
|
||||
var e = clite.user.getGRDataInd(grentind);
|
||||
if (e !== null)
|
||||
grentind++;
|
||||
return e;
|
||||
},
|
||||
setgrent:function() {
|
||||
grentind = 0;
|
||||
},
|
||||
|
||||
// gets teh group file data for a group based on their gid
|
||||
|
|
|
|||
Loading…
Reference in a new issue