I've been testing the PAM modules, and have made some minor changes
that improve the quality and security of the code.

        1) I didn't have the right return conditions in
readUserPubKey.  Occasionally the pam module would give a segmentation
error. This version is more stable.

        2) I've added code that allows the certificates to be stored in
the user's home directory, based on the value in the /etc/passwd file.
The original version would use /home/username, even though root's home
directory was /root

        3) I've added checks to make sure the certificates in the home
directory are not group or world writable. It checks the file, the
directory, and all directories above. It also makes sure the file is
not a symbolic link.  It also uses these checks on the file
/etc/musclepam/pam-muscle.conf. It also makes sure the path to the
certificates is absolute, and does not contain the string "..", which
is perhaps over-paranoid.

 
        4) I've added documentation on getting it to work with
xscreensaver and GDM.


---------------------------------------------------------------

2004-10-04 15:03  diff -lb pam_smartcard.c.orig pam_smartcard.c   Page 1


45c45
<  * This struct contains secure data and shoul be overwritten
---
>  * This struct contains secure data and should be overwritten
256c256
<   int rv;
---
>   int rv = 0;
262c262,264
<   snprintf(homeFile, 200, "%s%s/.muscle/%s", pr.userpath, sd->user, pr.certname);  
---
>   /* Is userpath defined? If so, use it as a way to find someone's
>    home directory. I'm using this because the existence of the
>    specified file overrides the end user's default certificate */
263a266,281
>   if (strlen(pr.userpath)>0) {
>       snprintf(homeFile, 200, "%s%s/.muscle/%s", pr.userpath, sd->user, 
> pr.certname);  
>   } else {
>       /* It's not defined. We have to determine the user's home directory. */
>       struct passwd *pw;
>       if ((pw=getpwnam(sd->user)) == NULL) {
>         syslog(LOG_ERR, "su attempt to non-existing user: %s", sd->user);
>         return -1;
>       } else {
>         snprintf(homeFile, 200, "%s/.muscle/%s", pw->pw_dir, pr.certname);  
>       }
>   }
>   if (util_CheckFile(homeFile,(char *)(sd->user))) {
>       syslog(LOG_ERR, "Unsafe permissions on user certificate, file: %s: user: %s", 
> homeFile, sd->user);
>       return -1;
>   }
273a292
>       if (pr.debug) syslog(LOG_INFO, "user certificate successfully read from %s", 
> homeFile);
275d293
<       syslog(LOG_ERR, "user certificate successfully read from %s", homeFile);
280,282c298
<         pcsc_release(&pConnection);
<         pam_release_data(sd);
<         return PAM_AUTHINFO_UNAVAIL;
---
>         return -1;
289,291c305
<     pcsc_release(&pConnection);
<     pam_release_data(sd);
<     return PAM_AUTHINFO_UNAVAIL;
---
>       return -1;
296d309
< 
442c455,457
<       if (rv != 0)
---
>       if (rv != 0) {
>         pcsc_release(&pConnection);
>         pam_release_data(sd);
443a459







2004-10-04 15:03  diff -lb pam_smartcard.c.orig pam_smartcard.c   Page 2


>       }
457c473
<   /* This sectionj can be used to verify the user's certificate */
---
>   /* This section can be used to verify the user's certificate */
460c476
<       syslog(LOG_ERR, "Public key file read from user certificate");
---
>       syslog(LOG_INFO, "Public key file read from user certificate");
516a533
>         pam_release_data(sd);
530c547
<               printf("%02x", rv);
---
>               printf("%02X", rv);
564c581
<       if (pr.debug)
---
>       if (pr.debug) {
565a583,584
>         printf("Challenge failed\n");
>       }









































2004-10-04 15:03    diff -lb preferences.c.orig preferences.c     Page 1


9a10
>  *   Bruce Barnett        <[EMAIL PROTECTED]>
22c23,27
< 
---
> #include <sys/types.h>
> #include <sys/stat.h>
> #include <unistd.h>
> #include <pwd.h>
> #include <sys/types.h>
24a30,32
> /* The third parameter was /home, but this overrides the default value
>    of the home directory specified by the passwd file */
> 
29c37
<   "/home/",
---
>   "",   /* was "/home/" */
196a205,209
>   if (pr.debug) syslog(LOG_INFO, "Reading the preferences from file '%s'", 
> rcfilename);
> 
>   if (util_CheckFile(rcfilename,"root")) {
>       return -1;
>   }
203d215
<       
208a221,339
> /******************************************************************************
> ** Function: util_CheckFile
> **
> ** Checks to make sure the file is not modifyable by someone other
> ** than the owner This utility is given the complete name for the file
> ** and recursively walks up the direwctory tree until it reaches the
> ** root directory.
> **
> **
> ** Parameters:
> **  file (string)
> **   user (string)
> **
> ** Returns:
> **  zero if no problem
> **  -1 if there is a security risk
> **  -2 if the file does not exist
> **
> 
> ******************************************************************************/
> 
> int util_CheckFile (char *file, char *user) {
>       char path[1024];
>       int i;
>       char *l;
> 
>       if (strstr(file,"..")) {
>         /* This would probably never happen, and the owner of the
>                /etc/musclepam/pam-muscle.conf file has to put it







2004-10-04 15:03    diff -lb preferences.c.orig preferences.c     Page 2


>                there. . But it's better to be paranoid and safe than
>                sorry */
>         syslog(LOG_ERR, "File '%s' contains the string '..'  - unsafe place to put 
> configuration file", file);
>         return -1;
>       }
> 
>       if (file[0] != '/') {
>         syslog(LOG_ERR, "File '%s' is relative. Must use absolute path  - unsafe 
> place to put configuration file", file);
>         return -1;
>       }                       
> 
>       /* Now - check the entire file */
>       if ((i=util_CheckFileComponent(file,user))<0) return i;
>       /* looks okay - now check all of the paths */
>       (void)strncpy(path,file,1024);
>       while ((l=strrchr(path,'/')) != NULL) {
>         /* chop off all characters after the '/' */
>         *l=0;
>         if (strlen(path)) {
>               if ((i=util_CheckFileComponent(path,user)) <0) return i;
>         }     
>       }
>          
>       if (pr.debug) 
>         syslog(LOG_INFO, "File '%s' and user %s look okay", file, user);
>       return 0;
> }
> 
> /******************************************************************************
> ** Function: util_CheckFileComponent
> **
> ** Checks to make sure the file component (either a single file or
> ** directory) is not modifyable by someone other than the owner
> **
> ** Parameters:
> **  file (string)
> **   user (string)
> **
> ** Returns:
> **  zero if no problem
> **  -1 if there is a security risk
> **  -2 if the file or directory does not exist
> **
> 
> ******************************************************************************/
> 
> int util_CheckFileComponent (char *file, char *user) {
>     struct stat buf;
>       struct passwd *pw;
>       uid_t uid;
> 
>       /* Check if the file is a symbolic link */
>       if (lstat(file,&buf)) {
>         /* if (pr.debug) printf("File does not exist %s - done\n", file); */
>         return -2; /* doesn't exist */
>       }







2004-10-04 15:03    diff -lb preferences.c.orig preferences.c     Page 3


> 
> 
>       if (S_ISLNK(buf.st_mode)) {
>         syslog(LOG_ERR, "File '%s' is a symbolic link - unsafe place to put 
> configuration file", file);
>         return -1;
>       } 
>   
>       /* Check the real file */
>       if (stat(file,&buf)) {
>         /* if (pr.debug) printf("File does not exist (2) %s - done\n", file); */
>         return -2; /* I can't check it, so it's okay */
>       };
>   
>       /* Find the user's UID number */
>       if ((pw=getpwnam(user)) == NULL) {
>         syslog(LOG_ERR, "User '%s' does not exist", user);
>         return -1;
>       }
>  
>       uid=pw->pw_uid;
> 
>       if ((buf.st_uid != uid) && (buf.st_uid != 0)) {
>         syslog(LOG_ERR, "File '%s' is  owned by UID %d, and should be owned by %d 
> (%s) - unsafe operation", file, buf.st_uid, uid, user);
>         return -1;
>       }
> 
>       if ((buf.st_mode & 0022) != 0) {
>         /* if (pr.debug) printf("File mode is BAD,  %o vs. %o\n", buf.st_mode, 
> (buf.st_mode&022)); */
>         syslog(LOG_ERR, "File '%s' is group or world writable - may be unsafe 
> operation", file);
>         return -1;
>       }
>       return 0;
> }
> 





























2004-10-04 15:03    diff -lb preferences.h.orig preferences.h     Page 1


42a43,47
> /* Check the permissions of the file */
> int util_CheckFile (char *file, char *user);
> 
> /* Check the permissions of the file Component*/
> int util_CheckFileComponent (char *file, char *user);

























































2004-10-04 15:03           diff -lb README.orig README            Page 1


45c45,49
<                 certificate. 
---
>               certificate. If the file contains a value for UserPath, then
>               this is used instead of the user's home directory. This allows
>               the admin to create a directory containing certificates that
>               are not modify able by the user. Of it can be used for testing.
> 
62a67
>               This is also in base64 format, and has the form
67a73
>       
104,123c110,216
< Note that the user can do this without any outside authority. Make sure
< the home directory and certificate is not writable. (pam_musclecard.so
< should check to make sure this is not possible. However it doesn't, so
< this is a potential security problem).
< 
< Once you have the certificate in place, I have been able to get the su
< and login modules to work with PAM.
< 
< Modify
<     /etc/pam.d/su
< to contain
<    auth       required     /lib/security/pam_musclecard.so service=system-auth
< 
<  and /etc/pam.d/login to contain
<    auth       required /lib/security/pam_musclecard.so service=system-auth
< 
< and when you try to log into the console, or to do an su, it first
< checks if a smartcard is plugged in. If so, it asks for a PIN value.
< Then it procees to verify it with the user's ~user/.muscle/user.cert
< file.
---
>       Also not that you have to change the certificate number from 0
>       (which is the private key) to 1, which would in this case be the
>       public key.
> 
> Note that the user can do this without any outside authority. 
> 
> The pam module makes sure that only the user and root has write access
> to the certificate.  The certificate, and all of the directories
> above, cannot be group or world writable, and have to be owned by the
> user or root. Otherwise, the user is not allowed to log in, and a log
> message is written to the log file.
> 
> Once you have the certificate in place, you can use PAM to add
> smartcard authentication to the following modules [I have verified
> that these work on Fedora Core 1. Other applications might work as
> well, but I have not tested them.  -Bruce]
> 
>       login
>       su
>       xscreensaver
>       gdm
>       gdm-autologin







2004-10-04 15:03           diff -lb README.orig README            Page 2


> 
> 
> The modifications to the /etc/pam.d/* files only change the auth
> values (lines whose first column is "auth")
> 
> Gdm requires both a password and a PIN value.
> xscreeensaver only requires a PIN value, but asks for a password.
> This seems to be a bug in xscreensaver.
> 
> 
> ::::::::::::::
> gdm-autologin
> ::::::::::::::
> #%PAM-1.0
> auth       required   pam_env.so
> auth       required   pam_musclecard.so service=system-auth
> auth       required   pam_nologin.so
> auth       required   pam_permit.so
> account    required   pam_stack.so service=system-auth
> password   required   pam_stack.so service=system-auth
> session    required   pam_stack.so service=system-auth
> session    optional     pam_console.so
> ::::::::::::::
> gdmsetup
> ::::::::::::::
> #%PAM-1.0
> auth       sufficient   pam_rootok.so
> auth       sufficient   pam_timestamp.so
> auth       required     pam_stack.so service=system-auth
> auth       required     pam_musclecard.so service=system-auth debug
> session    required     pam_permit.so
> session    optional     pam_xauth.so
> session    optional     pam_timestamp.so
> account    required     pam_permit.so
> ::::::::::::::
> gdm
> ::::::::::::::
> #%PAM-1.0
> auth       required   pam_env.so
> #auth       required  pam_stack.so service=system-auth
> auth       required   pam_musclecard.so service=system-auth debug
> # If you are sure, you may want to remove the next line
> # It allows root to log in without a smartcard
> auth       required   pam_nologin.so
> account    required   pam_stack.so service=system-auth
> password   required   pam_stack.so service=system-auth
> session    required   pam_stack.so service=system-auth
> session    optional     pam_console.so
> ::::::::::::::
> login
> ::::::::::::::
> #%PAM-1.0
> #auth       required  pam_securetty.so
> auth       required   /lib/security/pam_musclecard.so service=system-auth
> #auth       required  pam_stack.so service=system-auth
> #auth       required  pam_nologin.so







2004-10-04 15:03           diff -lb README.orig README            Page 3


> account    required   pam_stack.so service=system-auth
> password   required   pam_stack.so service=system-auth
> session    required   pam_stack.so service=system-auth
> session    optional   pam_console.so
> ::::::::::::::
> su
> ::::::::::::::
> #%PAM-1.0
> auth       sufficient   /lib/security/$ISA/pam_rootok.so
> # Uncomment the following line to implicitly trust users in the "wheel" group.
> #auth       sufficient   /lib/security/$ISA/pam_wheel.so trust use_uid
> # Uncomment the following line to require a user to be in the "wheel" group.
> #auth       required     /lib/security/$ISA/pam_wheel.so use_uid
> #was
> #auth       required  /lib/security/$ISA/pam_stack.so service=system-auth
> auth       required   /lib/security/pam_musclecard.so service=system-auth 
> account    required   /lib/security/$ISA/pam_stack.so service=system-auth
> password   required   /lib/security/$ISA/pam_stack.so service=system-auth
> session    required   /lib/security/$ISA/pam_stack.so service=system-auth
> session    optional   /lib/security/$ISA/pam_xauth.so
> ::::::::::::::
> xscreensaver
> ::::::::::::::
> #%PAM-1.0
> 
> # Red Hat says this is right for them, as of 7.3:
> auth       required   pam_stack.so service=system-auth
> auth       required   /lib/security/pam_musclecard.so service=system-auth  debug
> # auth       required pam_pwdb.so shadow nullok


































2004-10-04 15:04  diff -lb pam-muscle.conf.orig pam-muscle.conf   Page 1


8c8,9
< CertNumber  = 0                         # Certificate number to use
---
> # Usually, cert #0 is the private key, and cert# 1 is the public key
> CertNumber  = 1                         # Certificate number to use
10d10
< UserPath    = /home/                    # Path to user home directory
11a12,15
> # If the following value is defined, then it is used to determine the
> # location of the user certificate - i.e. $UserPath/$USER/.muscle/$CertName
> # Otherwise, the user's home directory is used - i.e. ~user/.muscle/$CertName
> #UserPath    = /home/                    # Path to user home directory

















































_______________________________________________
Muscle mailing list
[EMAIL PROTECTED]
http://lists.drizzle.com/mailman/listinfo/muscle

Reply via email to