106 OS homework 2-2 成果報告書

組長:B10415030、黃智威
組員:B10415022、賴麒文
組員:B10415041、曾增宇
github: https://github.com/Will03/xv6-public


🙂 使用情境說明(包含流程圖)

系統架構圖

我們希望建構出安全多人的權限管理系統,因此我們必須在proc新增uid/gid欄位,來存放是誰使用這個process。在inode中新增ownerid, groupid, permission(權限值), attribute(屬性值),並藉由操作proc 和 inode來完成,以此來提高資料安全的方法。

系統流程圖

第一部份 使用者登入功能

1. 開機登入

2. funciotn call: su(切換帳戶)

3. function call: useradd(新增使用者)

4. process UID/GID

第二部份 權限控管

1. 使用者進行檔案操作

2. systemcall: chmod

3. function call: mv

第三部份 針對系統重要檔案進行安全防護(如:密碼檔等

1. 將檔名首字為點的檔案進行隱藏,如:.userpasswd、.nowuserid

2. log 檔: 記錄登錄資訊

.bash_history 內容

3. systemcall: chattr(改變檔案屬性)、lsattr(列出目前檔案屬性)

4. 使用隨機數的XOR來加密密碼檔的密碼

第四部份 增加檔案系統功能

1. 可在任何資料夾下下指令

2. 路徑標示


😇 成功畫面

第一部份 使用者登入功能

  1. 登入過程:登入使用者Will,並核對密碼,若失敗則需重新輸入

  1. su 切換使用者:從Will切換成Peter

  1. useradd:新增Leo為新的使用者,並設定其密碼

  1. ps:顯示每個process的資訊,一開始為0(root),登入後會改為使用者的id

第二部份 權限控管系統

  1. ls:列出該目錄沒被隱藏的所有檔案

  1. cd:開啟資料夾,若無權限則開啟失敗

  1. mkdir:新增一個具有權限的資料夾,創建者設為owner

  1. chmod:改變該檔案的權限,若無改變的權限則deny

  1. rm:刪除檔案,若無權限則deny

第三部份 針對系統重要檔案進行安全防護

  1. 創隱藏檔:在檔案名前加.視為創建隱藏檔,無法被ls列出

  1. chattr & lsattr: 更改並顯示檔案屬性值 1代表任何人都無法做更動

  1. 開啟log檔:列出指令的歷史紀錄

第四部份 增加檔案系統功能

  1. mv:將某檔案的內容更改為指定檔案的內容


🏃 實作過程(修改哪些檔案[含圖片])

修改
file.h
fs.h
mkfs.c
proc.c
proc.h
sh.c
syscall.c
syscall.h
sysfile.c
usys.S
sysproc.c
user.h
defs.h
cat.c
ls.c

新增
chattr.c
chmod.c
lsattr.c
login.c
mv.c
passwork.h
ps.c
su.c
useradd.c

file.h

struct inode {
  uint dev;           // Device number
  uint inum;          // Inode number
  int ref;            // Reference count
  struct sleeplock lock; // protects everything below here
  int valid;          // inode has been read from disk?

  short type;         // copy of disk inode
  short major;
  short minor;
  short nlink;
  uint size;
  uint addrs[NDIRECT+1];

  short ownerid;        // The ID of the user who owns the file.
  short groupid;        // The ID of the group who owns the file.
  short permission;           // The files mode e.g. 0700
  short attributes;
};

fs.h

struct dinode {
  short type;           // File type
  short major;          // Major device number (T_DEV only)
  short minor;          // Minor device number (T_DEV only)
  short nlink;          // Number of links to inode in file system
  uint size;            // Size of file (bytes)
  uint addrs[NDIRECT+1];   // Data block addresses

  short ownerid;        // The ID of the user who owns the file.
  short groupid;        // The ID of the group who owns the file.
  short permission;     // The files mode e.g. 0700
  short attributes;     // The files attributes 0 or 1
};

mkfs.c

uint
ialloc(ushort type)
{
  uint inum = freeinode++;
  struct dinode din;

  bzero(&din, sizeof(din));
  din.type = xshort(type);
  din.nlink = xshort(1);
  din.size = xint(0);

  // Set notable defaults for our permission attributes.
  din.ownerid = xshort(0);
  din.groupid = xshort(0);
  din.permission = xshort(777);
  din.attributes = xshort(0);
  winode(inum, &din);
  return inum;
}

proc.c


void
ps(void)
{
  struct proc *p;

  //sti();
  acquire(&ptable.lock);
  cprintf("UID\tGID\t\t name \t pid \t state \n\n");
  for(p = ptable.proc; p < &ptable.proc[NPROC]; p++)
  {
    if(p->state == SLEEPING)
    {
      cprintf("%d\t%d\t\t %s \t %d \t SLEEPING\n",p->gid,p->uid,p->name,p->pid);
    }
    else if(p->state == RUNNING)
    {
      cprintf("%d\t%d\t\t %s \t %d \t RUNNING\n",p->gid,p->uid,p->name,p->pid);
    }
    else if(p->state == RUNNABLE)
    {
      cprintf("%d\t%d\t\t %s \t %d \t RUNNABLE\n",p->gid,p->uid,p->name,p->pid);
    }
  }

  release(&ptable.lock);
cprintf("\n");
  
}

int 
setuid(int uid,int mod){
    acquire(&ptable.lock);

    if(mod == 0)
      myproc()->uid = uid;  
    else if(mod == 1)
      myproc()->parent->uid = uid;
    
    release(&ptable.lock);
    return uid;
}

int 
setgid(int gid , int mod){
    acquire(&ptable.lock);

    if(mod == 0)
      myproc()->gid = gid;  
    else if(mod == 1)
      myproc()->parent->gid = gid;
    
    release(&ptable.lock);
    return gid;
}

int
getuid(void)
{
  return myproc()->uid;
}

proc.h

struct proc {
  uint sz;                     // Size of process memory (bytes)
  pde_t* pgdir;                // Page table
  char *kstack;                // Bottom of kernel stack for this process
  enum procstate state;        // Process state
  int pid;                     // Process ID
  struct proc *parent;         // Parent process
  struct trapframe *tf;        // Trap frame for current syscall
  struct context *context;     // swtch() here to run process
  void *chan;                  // If non-zero, sleeping on chan
  int killed;                  // If non-zero, have been killed
  struct file *ofile[NOFILE];  // Open files
  struct inode *cwd;           // Current directory
  char name[16];               // Process name (debugging)
  int uid;
  int gid;
};

sh.c

int
getnowid(char *id)
{
  int fd,num,now = 0;
  char buf[20];
  if((fd = open("/.nowuserid", O_RDONLY))>=0)
  {
    if((num = read(fd,buf,sizeof(buf)))>0){

      for(now = 0;now<num-1;now++){
        if(buf[now] < 48 || buf[now]> 57)break;
        id[now] = buf[now];
      }
      id[now] = '\0';
      close(fd);
      return 0;
    }
    close(fd);
    return -2;
  }
  close(fd);
  return -1;
}

int
main(int argc,char *argv[])
{
  username= argv[0];
  char *dir=malloc(100);
  static char buf[100];
  int fd, flag =0;

  strcpy(dir, "/home/");
  strcpy(dir + strlen(dir),username);
  chdir(dir);
  
  int i=0;
  int lastPos =0;
  int bash; 
  char id[5],idbuf[10];
  for(i=0;i<strlen(dir); i++)
  {
    path[i]=dir[i];
  }
  path[i]='/';
  lastPos =i;
  // Ensure that three file descriptors are open.
  while((fd = open("console", O_RDWR)) >= 0){
    if(fd >= 3){
      close(fd);
      break;
    }
  }
  bash = open("/.bash_history",O_CREATE | O_RDWR);   
  // Read and run input commands.
  while(getcmd(buf, sizeof(buf)) >= 0){
    if(buf[0]!='\n'){
      getnowid(id);
      strcpy(idbuf,"ID: ");
      strcpy(idbuf+strlen(idbuf),id);
      strcpy(idbuf+strlen(idbuf)," -> ");
      write(bash,idbuf,strlen(idbuf));
      write(bash, buf, strlen(buf));
    }
    if(buf[0] == 'c' && buf[1] == 'd' && buf[2] == ' '){
      // Chdir must be called by the parent, not the child.
      buf[strlen(buf)-1] = 0;  // chop \n
      if(strlen(path)==1 && (buf[3]=='.' && buf[4]=='.'))
      {
        printf(1, "cannot cd ..\n");
      }      
      else if((flag = chdir(buf+3)) < 0){
        if(flag == -2)
        {
          printf(2, "cannot cd %s :permission deny\n", buf+3);  
        }
        else
          printf(2, "cannot cd %s\n", buf+3);
      }
      else
      {
        if(buf[3]=='.' && buf[4] == '.')
        {
	        path[strlen(path)-1]='\0';
	        while(path[lastPos]!='/')
	        {
	          path[lastPos--]='\0';
     	    }
        }
	else if(buf[3]== '/' && (buf[4]== ' ' || buf[4]== '\0'))
	{
	  path[0]='/';
 	  int i;
	  for(i=1;i<strlen(path);i++)
	  {
	    path[i]=0;
	  }
	  lastPos=1;
	}
	else if(buf[3]=='.' && strlen(buf)==4)
	{
	  continue;
	}
	else
	{
	  int iter=3;
	  while(buf[iter]!='\0')
	  {
	    path[++lastPos]=buf[iter];
	    iter++;
	  }
          path[++lastPos]='/';
	  iter=3;
	}
      }
      continue;
    }
    if(fork1() == 0)
    {
      if(buf[0]=='\n')
      {
        runcmd(parsecmd(buf));
      }
      else
      {
        char p[sizeof(buf)+1];
        p[0]='/';
        int i=0;
        while(buf[i]!='\0')
        {
          p[i+1]=buf[i];
    	  i++;
        }
      runcmd(parsecmd(p));
      }
    }
    wait();
  }
  exit();
}

syscall.c

extern int sys_chmod(void);
extern int sys_lsfstat(void);
extern int sys_chattr(void);
extern int sys_cat(void);
extern int sys_ps(void);
extern int sys_getuid(void);
extern int sys_setuid(void);
extern int sys_setgid(void);
extern int sys_mv(void);

[SYS_chmod]   sys_chmod,
[SYS_lsfstat]   sys_lsfstat,
[SYS_chattr]   sys_chattr,
[SYS_cat]   sys_cat,
[SYS_ps]   sys_ps,
[SYS_getuid]   sys_getuid,
[SYS_setuid]   sys_setuid,
[SYS_setgid]   sys_setgid,
[SYS_mv]   sys_mv,

syscall.h

#define SYS_chmod  22
#define SYS_lsfstat  23
#define SYS_su  24
#define SYS_useradd  25
#define SYS_lsattr  26
#define SYS_chattr  27
#define SYS_cat 28
#define SYS_ps 29
#define SYS_setuid 30
#define SYS_setgid 31
#define SYS_getuid 32
#define SYS_mv 33

usys.S

SYSCALL(chmod)
SYSCALL(lsfstat)
SYSCALL(su)
SYSCALL(useradd)
SYSCALL(lsattr)
SYSCALL(chattr)
SYSCALL(cat)
SYSCALL(ps)
SYSCALL(getuid)
SYSCALL(setuid)
SYSCALL(setgid)
SYSCALL(mv)

user.h


int chmod(char*,int);
int lsfstat(int fd, struct stat*);
int chattr(char*,int);
int cat(char*);
int ps(void);
int setuid(int,int);
int setgid(int,int);
int getuid(void);
int mv(char*,char*);

sysfile.c

checkPermission(const struct inode *ip, int P_type)
{

  int nowid,idmode = 3;
  short premis = ip->permission;
  short attri = ip->attributes;
  
  if(attri && P_type==P_write)
  {
    return 0;
  }


  //use file to get uid/gid
  struct inode *id;
  char userid[30];
  int num,now;
  begin_op();
  if((id = namei("/.nowuserid\0"))==0){
    end_op();
    return -1;
  }
  ilock(id);
  num = readi(id,userid,0,sizeof(userid));
  end_op();
  iunlockput(id);
  nowid = 0;
  now = 0;
  for(now = 0;now<num-1;now++){
    if(userid[now] < 48 || userid[now]> 57)break;
    nowid *=10;
    nowid += (int)userid[now] - 48;  
  }
  if(ip->ownerid == nowid || nowid == 0)
  {
    idmode = 1;
  }
  else
  {
    for(;now<num-1;){
      nowid = 0;
      now++;
      for(;now<num-1 ;now++){
        if(userid[now] < 48 || userid[now]> 57)break;
        nowid *=10;
        nowid += (int)userid[now] - 48;  
      }
      
      if(ip->groupid == nowid){
        idmode = 2;
        break;
      }
      if(userid[now]!=';')break;
    }
  }

  //use process to get uid/gid
  
  // nowid = getuid();
  // if(ip->ownerid == nowid || nowid == 0)
  // {
  //   idmode = 1;
  // }
  // else if(ip->groupid == nowid){
  //   idmode = 2;   
  // }
  // else {
  //   idmode = 3;
  // }
  switch(idmode)
  {
    case 1:
      premis = premis/100;
      break;
    case 2:
      premis = ((premis % 100) - (premis % 10))/10;
      break;
    case 3:
      premis = premis % 10;
      break;
  }
  switch(P_type)
  {
    case P_read:
      if(premis>3)
        return 1;
      else
        return 0;
      break;
    case P_write:
      if(premis == 2 ||premis == 3 || premis == 6 || premis == 7 )
        return 1;
      else
        return 0;
      break;
    case P_execute:
      if(premis%2 > 0)
        return 1;
      else
        return 0;
      break;
    default:
      return 0;
  }
}
//change the file's attribute
int
sys_chattr(void)
{
  struct inode *id;
  char *path;
  int mod,num;
  char userid[30];
  int nowid,now;
  begin_op();
  
  if((id = namei("/.nowuserid\0"))==0){
    end_op();
    return -1;
  }
  ilock(id);
  num = readi(id,userid,0,sizeof(userid));
  end_op();
  iunlockput(id);
  nowid = 0;
  now = 0;
  begin_op();
  
  for(now = 0;now<num-1;now++){
    if(userid[now] < 48 || userid[now]> 57)break;
    nowid *=10;
    nowid += (int)userid[now] - 48;  
  }

  if(argstr(0, &path) < 0 || argint(1, &mod) < 0){
    end_op();
    return -1;
  }

  if((id = namei(path))==0){
    end_op();
    return -2;
  }
  if(mod<0 || mod > 100)
  {
    end_op();
    return -3;
  }

  if(nowid!=0){
    end_op();
    return -4;
  }

  ilock(id);

  id->attributes = mod;
  iupdate(id);
  iunlockput(id);
  end_op();

  return mod;
}

//change the file's permission
int
sys_chmod(void)
{
  struct inode *id;
  char *path;
  int mod,num;
  char userid[30];
  int nowid,now;
  begin_op();

  if((id = namei("/.nowuserid\0"))==0){
    end_op();
    return -1;
  }
  ilock(id);
  num = readi(id,userid,0,sizeof(userid));
  end_op();
  iunlockput(id);
  nowid = 0;
  now = 0;
  begin_op();
  
  for(now = 0;now<num-1;now++){
    if(userid[now] < 48 || userid[now]> 57)break;
    nowid *=10;
    nowid += (int)userid[now] - 48;  
  }
  if(argstr(0, &path) < 0 || argint(1, &mod) < 0){
    end_op();
    return -1;
  }
  if((id = namei(path))==0){
    end_op();
    return -2;
  }
  if(mod<100 || mod > 777)
  {
    end_op();
    return -3;
  }
  ilock(id);
  if(id->ownerid != nowid)
  {
    iupdate(id);
    iunlockput(id);
    end_op();
    return -4;
  }

  id->permission = mod;
  iupdate(id);
  iunlockput(id);
  end_op();

  return mod;
}

int
sys_cat(void)
{
  char *path;
  struct inode *id;
  begin_op();
  if(argstr(0, &path) < 0 ){
    end_op();
    return -1;
  }
  if((id = namei(path))==0){
    end_op();
    return -2;
  }

  if(checkPermission(id,P_read) == 0)
  {
    end_op();
    return -3;
  }
  end_op();
  return 0;
}
int
sys_mv(void)
{
  char *path,*path2;
  struct inode *id;
  char name[DIRSIZ];
  begin_op();
  if(argstr(0, &path) < 0 ||argstr(1, &path2) < 0 ){
    end_op();
    return -1;
  }
  if((id = nameiparent(path,name))==0){
    end_op();
    return -2;
  }
  
  if(checkPermission(id,P_write) == 0)
  {
    end_op();
    return -3;
  }
  end_op();

  begin_op();

  if((id = namei(path))==0){
    end_op();
    return -2;
  }
  
  if(checkPermission(id,P_read) == 0)
  {
    end_op();
    return -3;
  }
  end_op();

  begin_op();
  if((id = nameiparent(path2,name))==0){
    end_op();
    return -2;
  }
  end_op();
  if(checkPermission(id,P_write) == 0)
  {
    
    return -3;
  }

  return 0;
}

sysproc.c

int
sys_ps(void)
{
  ps();
  return 0;
}
int
sys_setuid(void)
{
  int uid;
  int mod;

  if((argint(0, &uid) < 0))
    return -1;
  
  if((argint(1, &mod) < 0))
    return -1;
  
  return setuid(uid,mod);
}
int
sys_setgid(void)
{
  int gid;
  int mod;

  if(argint(0, &gid) < 0 )
    return -1;
 
  if((argint(1, &mod) < 0))
    return -1;
  
  return setgid(gid,mod);
}
int
sys_getuid(void)
{
  
  return getuid();
}

defs.h

void            ps(void);
int             setuid(int,int);
int             setgid(int,int);
int             getuid(void);
int             getgid(void);

新增
chattr.c

#include "types.h"
#include "user.h"
#include "syscall.h"
int
main(int argc, char *argv[])
{
    int flag = 0;
    int attrmode = 0;
    if(argc != 3)
    {
        printf(2,"chattr: You enter wrong input \nHelp: Please enter the fliename and mode\n");
        exit();
    }
    if(!strcmp( argv[1],"-i"))
    {
        attrmode = 0;
    }
    else if(!strcmp( argv[1],"+i"))
    {
        attrmode = 1;
    }
    else 
    {
        printf(2,"chattr: You enter wrong attrmode %s\n",argv[1]);
        exit();
    }

    if((flag = chattr(argv[2],attrmode))>=0){
        printf(2,"chattr flag = %d\n",flag);
    }
    else if(flag == -1)
    {
        printf(2,"chattr: You enter wrong input \nHelp: Please enter the fliename and mode\n");
    }
    else if(flag == -2)
    {
        printf(2,"chattr: Your input file %s is not exist\n",argv[2]);
    }
    else if(flag == -3)
    {
        printf(2,"chattr: You input mode not in the range\n");
    }
    else if(flag == -4)
    {
        printf(2,"chattr: permission deny\n");
    }
    exit();
}

chmod.c

#include "types.h"
#include "user.h"
#include "syscall.h"
int
main(int argc, char *argv[])
{
    int flag = 0;
    if(argc != 3)
    {
        printf(2,"chmod: You enter wrong input \nHelp: Please enter the fliename and mode\n");
        exit();
    }
    if((flag = chmod(argv[2],atoi(argv[1])))>100){
    printf(2,"chmod flag = %d\n",flag);
    }
    else if(flag == -1)
    {
        printf(2,"chmod: You enter wrong input \nHelp: Please enter the fliename and mode\n");
    }
    else if(flag == -2)
    {
        printf(2,"chmod: Your input file %s is not exist\n",argv[2]);
    }
    else if(flag == -3)
    {
        printf(2,"chmod: You input mode not in the range\n");
    }
    else if(flag == -4)
    {
        printf(2,"chattr: permission deny\n");
    }
    exit();
}

lsattr.c

#include "types.h"
#include "stat.h"
#include "user.h"
#include "fs.h"

char*
fmtname(char *path)
{
  static char buf[DIRSIZ+1];
  char *p;

  // Find first character after last slash.
  for(p=path+strlen(path); p >= path && *p != '/'; p--)
    ;
  p++;

  // Return blank-padded name.
  if(strlen(p) >= DIRSIZ)
    return p;
  memmove(buf, p, strlen(p));
  memset(buf+strlen(p), ' ', DIRSIZ-strlen(p));
  return buf;
}

void
ls(char *path)
{
  char buf[512], *p;
  int fd , flag = 0;
  struct dirent de;
  struct stat st;

  if((fd = open(path, 0)) < 0){
    printf(2, "ls: cannot open %s\n", path);
    return;
  }

  if((flag = (fstat(fd, &st))) < 0){
    if(flag <= -2)
      printf(2, "ls: cannot stat %s :permission deny\n", path);  
    else
      printf(2, "ls: cannot stat %s\n", path);
    close(fd);
    return;
  }

  switch(st.type){
  case T_FILE:
    printf(1, "%s %d\n", fmtname(path), st.attribute);
    break;

  case T_DIR:
    if(strlen(path) + 1 + DIRSIZ + 1 > sizeof buf){
      printf(1, "ls: path too long\n");
      break;
    }
    strcpy(buf, path);
    p = buf+strlen(buf);
    *p++ = '/';
    while(read(fd, &de, sizeof(de)) == sizeof(de)){
      if(de.inum == 0)
        continue;
      memmove(p, de.name, DIRSIZ);
      p[DIRSIZ] = 0;
      if(stat(buf, &st) < 0){
        printf(1, "ls: cannot stat %s\n", buf);
        continue;
      }
      printf(1, "%s %d\n", fmtname(buf), st.attribute);
    }
    break;
  }
  close(fd);
}


int
main(int argc, char *argv[])
{
  int i;

  if(argc < 2){
    ls(".");
    exit();
  }
  for(i=1; i<argc; i++)
    ls(argv[i]);
  exit();
}

login.c

#include "types.h"
#include "user.h"
#include "stat.h"
#include "fcntl.h"
#include "passwork.h"
#define MAXLEN 20
char *argv[] = { "sh", 0 };

int
CheckAccount(int fd ,int writefd, char *user , char *passwd)
{
    char allWord[128];
    char Auser[MAXLEN];
    char AID[10];
    char Apassword[MAXLEN];
    char cipher[MAXLEN];
    int num;

    if(user[strlen(user)-1]  == '\n'){
  	    user[strlen(user)-1]  = '\0';	
    }
    if(passwd[strlen(passwd)-1]  == '\n'){
  	    passwd[strlen(passwd)-1]  = '\0';	
    }

    while((num = read(fd, allWord, sizeof(allWord))) > 0){
        //printf(1,"%d\n",num);  
        for(int i =0;i<num;i++)
        {

            i = readpasswdfile(allWord,Auser,Apassword,AID,num,i);
            if(i == -1)break;
            
            
            
            encodepasswd(cipher,passwd);

            if(!strcmp(user,Auser) && !strcmp(cipher,Apassword)){


                if(write(writefd,AID,sizeof(AID)) <= 0)
                    printf(1,"error\n");
                int now = 0,id = 0,mod = 0;
            

                for(int i =0 ;AID[i]!=';'&& AID[i]!='\0';i++,now++){
                    id *= 10;
                    
                    id += AID[i] - 48;
                }
                printf(2,"uid = %d gid = %d\n",setuid(id,mod),setgid(id,mod));
      	        return 1;
            }
            //while(i <num && allWord[i++] != '\n');
        }
    }
    return 0;
}

int
main(void)
{
    int pid = 0,fd,writefd, wpid;
    char * username;
    char namebuf[MAXLEN];
    char passwdbuf[MAXLEN];
    char* password;
    mkdir("/home/");
    chmod("home",777);
    while(1)
    {
        printf(1,"Username: ");
		username = gets(namebuf, MAXLEN);
		
        printf(1,"Password: ");
		password = gets(passwdbuf, MAXLEN);


        dup(0);  // stdout
	    dup(0);  // stderr
        //printf(1, "init:
        if((writefd = open("/.nowuserid", O_WRONLY)) < 0){
            printf(1,"Login: can't open nowuserid\n");
            break;
        } 
        if((fd = open("/.userpasswd", O_RDONLY)) < 0){
            printf(1,"Login: can't open Userpassword\n");
            break;
        }
        
        if(CheckAccount(fd,writefd,username,password)){
	        close(fd);
            close(writefd);
	    
            printf(2,"Hello %s, have a nice's day\n", username);            
            if((writefd = open("/.nowuserid", O_RDONLY)) < 0){
            printf(1,"Login: can't open nowuserid\n");
            break; } 
            char a[20];
            if(read(writefd,a,sizeof(a))<=0)
                printf(1,"error\n");
            printf(2,"%s\n",a);
           
            pid = fork();
            if(pid < 0){
                printf(1, "login: fork failed\n");
                exit();
            }
            if(pid == 0){   
                char * uname[] = {username,0};
		        char * dirToCreate = "/home/";
      	    	strcpy(dirToCreate + strlen(dirToCreate), username);
                mkdir(dirToCreate);
                exec("sh", uname);
                printf(1, "login: exec sh failed\n");
                exit();
            }
        }
        else{
            close(fd);
            close(writefd);
            printf(1,"you print error username or password\n");
            printf(1,"please input your account again\n");
        }

        close(fd);
        while((wpid=wait()) >= 0 && wpid != pid)
	    printf(1, "zombie!\n");
    }
    

    wait();
	exit();
	return 0;
}

mv.c

#include "types.h"
#include "stat.h"
#include "user.h"
#include "fs.h"
#include "fcntl.h"

#define BUFFER_SIZE 256

int
main(int argc, char *argv[]){
  if(argc != 3){
    printf(1, "Command Error, please check the argument.\n");
    exit();
  }


  int flag = mv(argv[1],argv[2]);
  if(flag <0){ 
    if(flag == -3){
      printf(1, "mv: permission deny.\n");
    }
    else if(flag == -2){
      printf(1, "mv: error to open the file.\n");
    }
    else if(flag == -1){
      printf(1, "mv: error to open the file.\n");
    }
    exit();
  }
  else{
    printf(1,"good\n");
  }


  int source = open(argv[1], 0);
  if(source == -1){
    printf(1, "Source file can not open.\n");
    exit();
  }

  
  int distination = open(argv[2], O_WRONLY | O_CREATE);
  if(distination == -1){
    printf(1, "Distination file can not write, Please Contact the root.\n");
    exit();
  }
  else if(distination == -2){
    printf(1, "mv: permission deny.\n");
    exit();
  }

  char buffer[BUFFER_SIZE];
  int length = 0;
  while((length = read(source, buffer, BUFFER_SIZE)) > 0)
    write(distination, buffer, length);

  close(source);
  close(distination);

  if(unlink(argv[1]) < 0)
    printf(1, "Can not Delete Source file.\n");
  exit();
}

passwork.h

#include "types.h"
#include "user.h"
#include "syscall.h"
#include "fcntl.h"

int
readpasswdfile(char* allWord,char* Auser,char* Apassword ,char* AID,int num,int i)
{
    int now = 0;
    for(;allWord[i]!=';'||i == num;i++,now++){
        Auser[now] = allWord[i];
    }
    i++;
    Auser[now] = '\0';
    if(i>=num){
        printf(1,"Login:AccountFile have error\n");
        return -1;
    }
    
    now =0;
    for(;allWord[i]!=';'||i == num;i++,now++){
        Apassword[now] = allWord[i];
    }
    i++;
    Apassword[now] = '\0';
    if(i>=num){
        printf(1,"Login:AccountFile have error\n");
        return -1;
    }
    //,char* passwdkey
    //Key string
    for(;allWord[i]!=';'||i == num;i++,now++);
    i++;
    if(i>=num){
        printf(1,"Login:AccountFile have error\n");
        return -1;
    }


    now =0;
    for(;allWord[i]!='\n' && allWord[i]!='\0' ;i++,now++){
        AID[now] = allWord[i];
    }
    AID[now] = '\0';
    // printf(1,"%s\n",Auser);
    // printf(1,"%s\n",Apassword);
    // printf(1,"%s\n",AID);
    return i;
}

//set a radom string
void pseudoRandom(char key, char encodeKey[], int len) {
  int i;
  unsigned char ran;
  unsigned char bnew;
  encodeKey[0] = key;
  for (i=1; i<len; i++) {
    ran = (unsigned char) encodeKey[i-1];
    bnew = (ran * 7) % 255;
    encodeKey[i] = (char) bnew;
  }
encodeKey[i] = '\0';
}
 
// start encrypt
void encrypt(char plan[], char cipher[], char encodeKey[], int len) {
  int i;
  for (i=0; i<len; i++) {
    cipher[i] = plan[i] ^ encodeKey[i];
    if(cipher[i]<0)cipher[i]*=-1;
    cipher[i] = (cipher[i]%25)+65;
  }
  cipher[i] = '\0';
}

void encodepasswd(char* cipher, char* passwd)
{
    char key = 0x6D;
    char encodeKey[20];
    pseudoRandom(key, encodeKey, strlen(passwd));
    encrypt(passwd, cipher, encodeKey,strlen(passwd));
}

ps.c

#include "types.h"
#include "stat.h"
#include "user.h"
int
main()
{
    ps();
    wait();
	exit();
	return 0;
}

su.c

#include "types.h"
#include "user.h"
#include "syscall.h"
#include "fcntl.h"
#include "passwork.h"
#define MAXLEN 20
int
CheckUser( int fd,char *user , char *passwd, char *ID)
{
    char allWord[128];
    char Auser[MAXLEN];
    char AID[MAXLEN];
    char Apassword[MAXLEN];
    int num = 0;
    if(user[strlen(user)-1]  == '\n'){
  	    user[strlen(user)-1]  = '\0';	
    }

    while((num = read(fd, allWord, sizeof(allWord))) > 0){
        for(int i =0;i<num;i++)
        {
            i = readpasswdfile(allWord,Auser,Apassword,AID,num,i);
            if(i == -1)break;
            
            if(!strcmp(user,Auser)){
                strcpy(passwd,Apassword);
                strcpy(ID,AID);
                return 1;
            }
        }
    }
    return 0;
}

int
main(int argc, char *argv[])
{
    int fd,writefd,flag = 0;
    char *userpasswd,*user = "";
    char password[MAXLEN],ID[MAXLEN];
    if((writefd = open("/.nowuserid", O_WRONLY)) < 0){
        printf(1,"su: can't open nowuserid\n");
        exit();
    } 
    if((fd = open("/.userpasswd", O_RDONLY)) < 0){
        close(writefd);
        printf(1,"su: can't open Userpassword\n");
        exit();
    }
    if(argc == 1)
    {
        flag = CheckUser(fd,"root",password,ID);
        strcpy(user,"root");
    }
    else if(argc == 2)
    {
        flag = CheckUser(fd, argv[1],password,ID);
        strcpy(user,argv[1]);
    }
    else
    {
        close(fd);
        close(writefd);
        printf(2,"su: error\n");
        exit();
    }

    if(flag == 1)
    {
        printf(1,"Password: ");
        userpasswd = gets("password", MAXLEN);

        if(userpasswd[strlen(userpasswd)-1]  == '\n'){
  	        userpasswd[strlen(userpasswd)-1]  = '\0';	
        }


        char cipher[MAXLEN];
        encodepasswd(cipher,userpasswd);
        
        
        if(!strcmp(cipher,password)){
            if(write(writefd,ID,sizeof(ID)) <= 0)
            {
                printf(1,"su: write file error\n");
                close(fd);
                close(writefd);
                exit();
            }
            
            if(write(writefd,ID,sizeof(ID)) <= 0)
                printf(1,"error\n");
            int now = 0,id = 0;
        

            for(int i =0 ;ID[i]!=';'&& ID[i]!='\0';i++,now++){
                id *= 10;
                
                id += ID[i] - 48;
            }
            setuid(id,1);
            setgid(id,1);
            //printf(2,"uid = %d gid = %d\n",);
            
            printf(2,"Welcome\n",user);
        }
         if(strcmp(cipher,password)!=0){
             printf(2,"su: user password error\n");
         }
    }
    else
    {
        printf(2,"su: no such user\n");
        close(fd);
        close(writefd);
        exit();
    }
    close(fd);
    close(writefd);
    exit();
}

useradd.c

#include "types.h"
#include "user.h"
#include "syscall.h"
#include "fcntl.h"
#include "passwork.h"
#define MAXLEN 20
int
seachlastuserid(char* allWord,int num,char* newid)
{
    int now = 0;
    char AID[10];
    for(int i =0;i<num;i++)
    {
        for(;allWord[i]!=';'||i == num;i++,now++);
        i++;
        if(i>=num){
            printf(1,"Login:AccountFile have error\n");
            return -1;
        }
        
        now =0;
        for(;allWord[i]!=';'||i == num;i++,now++);
        i++;
        if(i>=num){
            printf(1,"Login:AccountFile have error\n");
            return -1;
        }    

        now =0;
        for(;allWord[i]!=';'||i == num;i++,now++);
        i++;
        if(i>=num){
            printf(1,"Login:AccountFile have error\n");
            return -1;
        } 

        now =0;
        for(;allWord[i]!=';'||i == num;i++,now++){
            AID[now] = allWord[i];
        }
        for(;allWord[i]!='\n' && allWord[i]!='\0';i++,now++);
        AID[now] = '\0';
        //printf(1,"%s\n",AID);
        
    }
    int id = atoi(AID);
    int number = 0;
    char tem;
    id+=1;
    for(int n = 0;;number++)
    {
        n = id%10;
        id/=10;
        AID[number] = n+48;
        if(id==0)break;
    }
    for(int i =0,j=number;;i++,j--)
    {
        if(i >= j)break;
        tem = AID[i];
        AID[i] = AID[j];
        AID[j] = tem;
    }
    AID[number+1] = '\0';
    strcpy(newid,AID);
    return 1;
}

int main(int argc, char *argv[])
{
    int fd,num,flag = 0;
    char allWord[128],buf[64],newid[8],idbuf[17];
    char cipher[MAXLEN];
    if(argc != 3)
    {
        printf(2, "userpasswd: you need to input username and password\n");
        exit();
    }
    if((fd = open("/.userpasswd", O_RDONLY)) < 0){
        printf(1,"useradd: can't open Userpassword\n");
        exit();
    }
    while((num = read(fd, allWord, sizeof(allWord))) > 0){
        if(num>0){
            flag = seachlastuserid(allWord,num,newid);
        }
        else{
            printf(2,"useradd: error to read userpasswd\n");
            close(fd);
            exit();
        }
    }
    if(flag >0){
        printf(2,"id:%s\n",newid);
        for(num = 0;newid[num] == '\0';num++);
        num++;
        strcpy(idbuf,newid);
        strcpy(idbuf+strlen(idbuf),";");
        strcpy(idbuf+strlen(idbuf),newid);
        strcpy(idbuf+strlen(idbuf),"\n");
        // printf(2,"%d\n",num);
        // printf(2,"%s\n",idbuf);
        close(fd);
        if((fd = open("/.userpasswd", O_RDWR)) < 0){
            printf(1,"useradd: can't open Userpassword\n");
            exit();
        }
        if(read(fd, allWord, sizeof(allWord)) == 0){
            printf(2,"useradd: error to add new user\n");
            close(fd);
            exit();
        }
        strcpy(buf,argv[1]);
        strcpy(buf+strlen(buf),";");

        encodepasswd(cipher,argv[2]);
        strcpy(buf+strlen(buf),cipher);
        strcpy(buf+strlen(buf),";0x6D;");
        strcpy(buf+strlen(buf),idbuf);
        printf(2,"%s",buf);
        if( !write(fd, buf,strlen(buf))){
            printf(2,"useradd: error to add new user\n");
        }
        close(fd);
    }
    exit();
}

😎 結論

利用process來得到目前user的id,這個做法可以讓此系統成為一個多人多工個環境,因為系統會根據登入時使用者的不同,使process有不同的權限。完成後我們思考如何可以讓密碼檔和其它重要的檔案變得安全。所以我們新增了幾個蠻重要linux的一些安全措施。


📅 組員分工

黃智威:

賴麒文:

曾增宇: