Monday, September 1, 2014

Unix Prog: Password File

1. Password File Introduction
Password File in Unix is also called user database, which contains all user's information.

/etc/passwd:
 ubuntu@ip-172-31-23-227:~$ less /etc/passwd  
 ......  
 root:x:0:0:root:/root:/bin/bash  
 daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin  
 libuuid:x:100:101::/var/lib/libuuid:  
 ......  

1) 1st field is user name
2) 2nd field is placeholder for password. Normally the password is encrypted and saved in another file
3) 3rd field is numerical user id
4) 4th field is numerical group id
5) 5th field is comment
6) 6th field is default path where user login to
7) 7th field is default shell utility

Note:
1) There is usually one entry for "root" with user id 0(super user)
2) The encrypted password field contains a single character as a placeholder, since it is highly risky to just store password in this file which could be read by every one.
3) Some field may be empty.
4) If the 7th field is /dev/null, or /dev/true or /dev/false, its role is preventing user to login with this user name.

2. struct pwd
"struct pwd" is used to handle the password utility in unix programming.

definition:
 ubuntu@ip-172-31-23-227:~$ less /usr/include/pwd.h  
 ......  
 /* The passwd structure. */  
 struct passwd  
 {  
  char *pw_name;        /* Username. */  
  char *pw_passwd;       /* Password. */  
  __uid_t pw_uid;        /* User ID. */  
  __gid_t pw_gid;        /* Group ID. */  
  char *pw_gecos;        /* Real name. */  
  char *pw_dir;         /* Home directory. */  
  char *pw_shell;        /* Shell program. */  
 };  
 ......  

3. Password Files System Calls

Definition:
 ubuntu@ip-172-31-23-227:~$ less /usr/include/pwd.h  
 ......  
 /* Search for an entry with a matching user ID.  
   
   This function is a possible cancellation point and therefore not  
   marked with __THROW. */  
 extern struct passwd *getpwuid (__uid_t __uid);  
   
 /* Search for an entry with a matching username.  
   
   This function is a possible cancellation point and therefore not  
   marked with __THROW. */  
 extern struct passwd *getpwnam (const char *__name);  
 ......  
 /* Rewind the password-file stream.  
   
   This function is a possible cancellation point and therefore not  
   marked with __THROW. */  
 extern void setpwent (void);  
   
 /* Close the password-file stream.  
   
   This function is a possible cancellation point and therefore not  
   marked with __THROW. */  
 extern void endpwent (void);  
   
 /* Read an entry from the password-file stream, opening it if necessary.  
   
   This function is a possible cancellation point and therefore not  
   marked with __THROW. */  
 extern struct passwd *getpwent (void);  
 ......  

4. getpwuid, getpwnam

Given the user id or user name, return the struct passwd pointer referring to the corresponding struct.When calling it for more than one time, it will overwrite the same struct passwd(so, this is probably one static struct).

fileio.c:
 #include<stdio.h>  
 #include<stdlib.h>  
 #include<unistd.h>  
 #include<string.h>  
 #include<pwd.h>  
   
 void PrintPwd(struct passwd *pd)  
 {  
  printf("struct address: %p  ", pd);  
  printf("%s:%s:%d:%d:%s:%s:%s\n",  
      pd->pw_name, pd->pw_passwd, pd->pw_uid, pd->pw_gid,  
      pd->pw_gecos, pd->pw_dir, pd->pw_shell);  
 }  
   
 int main(int argc, char* argv[])  
 {  
  struct passwd *pd;  
  if((pd = getpwuid(0)) == NULL) {  
   printf("getpwduid error!\n");  
   exit(1);  
  }  
   
  PrintPwd(pd);  
   
  // following free call will cause error, this prove that returning  
  // struct passwd is not dynamically allocated. And we don't need to  
  // free it.  
  //free(pd);  
   
  if((pd = getpwnam("ubuntu")) == NULL) {  
   printf("getpwdnam error!\n");  
   exit(2);  
  }  
   
  PrintPwd(pd);  
   
  exit(0);  
 }  

shell:
Run the program, we can see that struct passwd addresses are different, so every time we call getpwuid or getpwnam, it will return a different struct. And it doesn't use "malloc" to dynamically create the struct, because we can't use free system call to free it.
 ubuntu@ip-172-31-23-227:~$ ./io.out  
 struct address: 0x7f0c1826b280  root:x:0:0:root:/root:/bin/bash  
 struct address: 0x7f0c1826b240  ubuntu:x:1000:1000:Ubuntu:/home/ubuntu:/bin/bash  

5. getpwent, setpwent, endpwent
setpwent: it will rewind all corresponding files to move their cursors to the beginning.
getpwent: it will retrieve next entry inside the passwd file. The first calling it will cause it open corresponding files.
endpwent: it will close all files opened by getpwent.

fileio.c:
 ubuntu@ip-172-31-23-227:~$ cat fileio.c  
 #include<stdio.h>  
 #include<stdlib.h>  
 #include<unistd.h>  
 #include<string.h>  
 #include<pwd.h>  
   
 void PrintPwd(struct passwd *pd)  
 {  
  printf("struct address: %p  ", pd);  
  printf("%s:%s:%d:%d:%s:%s:%s\n",  
      pd->pw_name, pd->pw_passwd, pd->pw_uid, pd->pw_gid,  
      pd->pw_gecos, pd->pw_dir, pd->pw_shell);  
 }  
   
 int main(int argc, char* argv[])  
 {  
  struct passwd *pd;  
   
  setpwent();  
  while((pd = getpwent()) != NULL) {  
   PrintPwd(pd);  
  }  
  endpwent();  
   
  exit(0);  
 }  

shell:
Run the program to iterate every entry in /etc/passwd. Note that for each address returned from "getpwent()", they are same. It indicates that getpwent just overwrite information at the same struct every time. And we still can NOT use "free" on this pointer address(invalid pointer), this means that this struct passwd is not dynamically allocated by "malloc".
 ubuntu@ip-172-31-23-227:~$ ./io.out  
 struct address: 0x7f63c3a9e200  root:x:0:0:root:/root:/bin/bash  
 struct address: 0x7f63c3a9e200  daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin  
 struct address: 0x7f63c3a9e200  bin:x:2:2:bin:/bin:/usr/sbin/nologin  
 struct address: 0x7f63c3a9e200  sys:x:3:3:sys:/dev:/usr/sbin/nologin  
 ......  

No comments:

Post a Comment