|
- Password and Shadow - Unix User Accounts Information
- Reading Notes by baif, 2004, Jan 18th.
- 1. Database files
- 1.1 Format of the Password File
- 1.2 Format of the Shadow File
- 1.3 Function crpyt()
- 2. What Can We do...
- 2.1 Shell
- 2.2 Getting Accounts Infourmantion with C
-
- To get more, refer to: 1.Linux Shadow Password HOWTO, 2.Unix Programming
-
-
-
- 1. Database files
- Unix/Linux's user accounts information were stored
- in the following files:
- /etc/passwd - user account information
- /etc/shadow - secure user account information
-
- drped from
- Linux Shadow Password HOWTO
- [url]http://www.linux.org/docs/ldp/howto/Shadow-Password-HOWTO.html[/url]
- 1.1 Format of the Password File
- A non-shadowed /etc/passwd file has the following format:
-
- username:passwd:UID:GID:full_name:directory:shell
- Where:
- username The user (login) name
- passwd The encoded password
- UID Numerical user ID
- GID Numerical default group ID
- full_name The user's full name - Actually this field is called the GECOS
- (General Electric Comprehensive Operating System) field and
- can store information other than just the full name.
- The Shadow commands and manual pages refer to this field as the comment field.
- directory User's home directory (Full pathname)
- shell User's login shell (Full Pathname)
- For example:
- username:Npge08pfz4wuk:503:100:Full Name:/home/username:/bin/sh
-
- Where Np is the salt and ge08pfz4wuk is the encoded password. The encoded salt/password could just
- as easily have been kbeMVnZM0oL7I and the two are exactly the same password. There are 4096 possible
- encodings for the same password.
- (The example password in this case is 'password', a really bad password).
- Once the shadow suite is installed, the /etc/passwd file would instead contain:
- username:x:503:100:Full Name:/home/username:/bin/sh
- The x in the second field in this case is now just a place holder. The format of the /etc/passwd file
- really didn't change, it just no longer contains the encoded password. This means that any program
- that reads the /etc/passwd file but does not actually need to verify passwords will still operate
- correctly.
- The passwords are now relocated to the shadow file (usually /etc/shadow file).
- 1.2 Format of the Shadow File
- The /etc/shadow file contains the following information:
-
- username:passwd:last:may:must:warn:expire:disable:reserved
-
- Where:
- username The User Name
- passwd The Encoded password
- last Days since Jan 1, 1970 that password was last changed
- may Days before password may be changed
- must Days after which password must be changed
- warn Days before password is to expire that user is warned
- expire Days after password expires that account is disabled
- disable Days since Jan 1, 1970 that account is disabled
- reserved A reserved field
- The previous example might then be:
-
- username:Npge08pfz4wuk:9479:0:10000::::
- 1.3 Function crpyt()
- From the crypt(3) manual page:
- "crypt is the password encryption function. It is based on the Data Encryption Standard algorithm
- with variations intended (among other things) to discourage use of hardware implementations of a
- key search. "
- [The] key is a user's typed password. [The encoded string is all NULLs]
- [The] salt is a two-character string chosen from the set [a-zA-Z0-9./].
- This string is used to perturb the algorithm in one of 4096 different ways.
- By taking the lowest 7 bit[s] of each character of the key, a 56-bit key is obtained. This 56-bit
- key is used to encrypt repeatedly a constant string (usually a string consisting of all zeros).
- The returned value points to the encrypted password, a series of 13 printable ASCII characters
- (the first two characters represent the salt itself). The return value points to static data whose
- content is overwritten by each call.
- 2. What Can We do...
- 2.1 Shell
- Some commands about accounts' operations
- User account operating:
- adduser: Creating new Users without option -D.
- userdel: Modifies the system account files, deleting all entries that refer to login. The named user must exist.
- Modifies the system account files in manual way:
- vipw: invork the command with -s option Modify the file /etc/shadow,
- invork without -s will modify /etc/passwd.
- chfn: Change the "finger name"(GECOS domain).
- chsh: Change the default Shell for specified account.
- passwd: Change the passwords of specified account.
- 2.2 Getting Accounts Infourmantion with C
- So, C provides some functions to read Unix accounts informantion. The information were stroed in files: passwd and shadow.
- First
- We should know about the definition of struct passwd in the <pwd.h> header, which includes at least the following members:
- struct passwd
- {
- char *pw_name /* user's login name */
- uid_t pw_uid /* numerical user ID */
- gid_t pw_gid /* numerical group ID */
- char *pw_dir /* initial working directory */
- char *pw_shell /* program to use as shell */
- /* The gid_t and uid_t types are defined as described in <sys/types.h> */
- }
- Seconed
- We can get the structure by the following two funtions for request entry:
- struct passwd * getpwnam(const char *); /* IT'S getpwnam(), NOT getpwname() */
- struct passwd * getpwuid(uid_t);
- The getpwnam() function searches the user database for an entry with a matching UserName, WHILE the getpwuid() funtion searches
- with maching UID.
- Those functions return pointers to a struct passwd with a matching entry if FOUND. A null pointer is returned if the requested
- entry is NOT found, or an ERORR occurs. On error, errno is set to indicate the error.
- Applications wishing to check for error situations should set errno to 0 before calling. To get more about error checking ,please
- turn to Manual.
- Example:
- __________________________________________________________________
- #include <stdio.h>
- #include <pwd.h>
- #include <limits.h>
- #include <sys/types.h>
- /* WITHOUT ERORR CHECKING */
- char * getuserhomedir_byun (char *user)
- {
- static char homedir[_POSIX_PATH_MAX]; /* defined in limits.h */
- struct passwd *pws;
- pws = getpwnam (user);
- if (!pws)
- return;
- strcpy (homedir, pws->pw_dir);
- return homedir;
- }
- char * getuserhomedir_byuid(uid_t uid) /* uid_t is defined in sys/types.h */
- {
- static char homedir[_POSIX_PATH_MAX];
- struct passwd * pws;
-
- pws = getpwuid(uid);
- if(!pws)
- return;
- strcpy(homedir, pws->pw_dir);
- return homedir;
- }
- int main (void)
- {
- printf("The user baif's home directory: %s\n", getuserhomedir_byun ("baif"));
- printf("Currnet process' UID is %d .The related home directory is %s\n", getuid(), getuserhomedir_byuid(getuid()) );
- }
- ____________________________________________________________________
- Third
- We can scan the user database by:
- struct passwd *getpwent(void);
- void endpwent(void);
- void setpwent(void);
- The getpwent() function returns a pointer to a structure containing the broken-out fields of an entry in the user database.
-
- Each entry in the user database contains a passwd structure. When first called, getpwent() returns a pointer to a passwd
- structure containing the first entry in the user database. Thereafter, it returns a pointer to a passwd structure
- containing the next entry in the user database. Successive calls can be used to search the entire user database.
- If an end-of-file or an error is encountered on reading, getpwent() returns a null pointer.
- The setpwent() function effectively rewinds the user database to allow repeated searches.
- The endpwent() function may be called to close the user database when processing is complete.
- In aother words, they are working just like files operations function, fgets(), fclose(),reset(). Can you follow me :P ?
-
- Successive callings of the getpent() will get a entry one by one(line by line in the user database file). The endpwent() will
- call the system function to close the database file in crrect way, while the setpwent() will re-open the database file.
- These interfaces need not be reentrant.
- Example:
- __________________________________________________________________
- #include <stdio.h>
- #include <pwd.h>
- #include <limits.h>
- #include <sys/types.h>
- /* WITHOUT ERORR CHECKING */
- /* Finds the hightest uid in passwd file and sets the nextued global variable to the next number. */
- void inituid(void)
- {
- struct passwd * entry;
- uid_t netxtuid = 0; /* uid_t is deifned in sys/types.h */
- printf("Scanning for next available uid... \r");
- fflush(stdout);
- while ( (entry = getpwent()) )
- if ( (entry->pw_uid > nextuid) &&
- (entry->pw_uid < 32767) ) /* Compensate for broken systems */
- nextuid = entry->pw_uid;
- endpwent();
- nextuid++;
- printf("The next uid will be %d%-20c.\n", nextuid, '.');
-
- }
- int main(void)
- {
- inituid();
- }
- __________________________________________________________________
- Others:
- int getpwnam_r(const char *, struct passwd *, char *, size_t, struct passwd **);
- int getpwuid_r(uid_t, struct passwd *, char *,size_t, struct passwd **);
- To get more, please refer to Manual.
复制代码 |
|