dtsession: implement screen lock/unlock for linux
authorJon Trulson <jon@radscan.com>
Thu, 12 Jul 2012 20:22:59 +0000 (14:22 -0600)
committerJon Trulson <jon@radscan.com>
Thu, 12 Jul 2012 20:22:59 +0000 (14:22 -0600)
In order for this to work, dtsession must be setuid root.  If
dtsession is not setuid root, then locking will be disabled, and a
message will be written to ~/.dt/errorlog with the message: "Unable to
lock display due to security restrictions".

cde/programs/dtsession/SmLock.c
cde/programs/dtsession/SmMain.c

index 7b0d5d6e2bbfa539e5b9a19a1e8a525c4acdb0ec..41b4abd7adb623ae8b31127d77525c46b55bdd53 100644 (file)
 #  include <shadow.h>
 #endif
 #endif
+
+#if defined(linux)
+# include <shadow.h>
+#endif
+#if defined(CSRG_BASED)
+#include <sys/types.h>
+#include <pwd.h>
+#endif
+
 #include "Sm.h"
 #include "SmUI.h"
 #include "SmError.h"
@@ -140,6 +149,93 @@ static void RequirePassword( XtPointer, XtIntervalId *) ;
 static void CycleSaver( XtPointer, XtIntervalId *) ;
 static void BlinkCaret( XtPointer, XtIntervalId *) ;
 
+#if defined(linux)
+/* #define JET_AUTHDEBUG */
+
+/* Test for re-auth ability - see if we can re-authenticate via pwd,
+ * shadow, or NIS
+ */
+static Boolean CanReAuthenticate(char *name, uid_t uid, char *passwd,
+                                struct passwd **pwent, struct spwd **spent)
+{
+  Boolean fail = False;
+
+  *pwent = (name == NULL) ? getpwuid(uid) : getpwnam(name);
+  *spent = getspnam((*pwent)->pw_name);
+
+#ifdef JET_AUTHDEBUG
+  fprintf(stderr, "CanReAuthenticate(): %s %s %s\n",
+         (*pwent) ? "PWENT" : "NULL",
+         (*spent) ? "SPENT" : "NULL",
+         (name) ? name : "NULL");
+#endif
+
+  /* some checking for aging stuff on RedPhat */
+
+  if (*pwent && (*pwent)->pw_passwd)
+    {
+      char *loc;
+
+      if ((loc = strchr((*pwent)->pw_passwd, ',')) != NULL)
+       *loc = '\0';
+#ifdef JET_AUTHDEBUG
+      fprintf(stderr, "CanReAuthenticate(): pw: '%s'\n",
+             (*pwent)->pw_passwd);
+#endif
+
+    }
+
+  if (*spent && (*spent)->sp_pwdp)
+    {
+      char *loc;
+
+      if ((loc = strchr((*spent)->sp_pwdp, ',')) != NULL)
+       *loc = '\0';
+    }
+
+  if (*pwent == NULL)
+    {                          /* if we can't get this, we're screwed. */
+#ifdef JET_AUTHDEBUG
+      fprintf(stderr, "CanReAuthenticate(): PWENT == NULL - FALSE\n");
+#endif
+      return False;
+    }
+
+  if ((*pwent)->pw_passwd == NULL)
+    {
+#ifdef JET_AUTHDEBUG
+      fprintf(stderr, "CanReAuthenticate(): (*pwent)->pw_passwd == NULL - FALSE\n");
+#endif
+
+      return False;
+    }
+
+  /* ok, now we have the prequisite data, look first to see if the
+   * passwd field is larger than 1 char - implying NIS, or a shadowed
+   * system.  if not look for *spent being non-NULL
+   */
+  if (*spent == NULL)
+    {                          /* if it's null, lets check for the NIS case */
+      if (strlen((*pwent)->pw_passwd) <= 1)
+       {
+#ifdef JET_AUTHDEBUG
+         fprintf(stderr, "strlen((*pwent)->pw_passwd) <= 1\n");
+#endif
+
+         return False;         /* not NIS */
+       }
+    }
+
+                               /* supposedly we have valid data */
+#ifdef JET_AUTHDEBUG
+      fprintf(stderr, "CanReAuthenticate(): TRUE\n");
+#endif
+
+  return True;
+}
+
+#endif /* linux */
+
 
 
 \f
@@ -185,21 +281,6 @@ LockDisplay(
 
     timerId = lockTimeId = lockDelayId = cycleId = flash_id = (XtIntervalId)0;
 
-    #if defined (SMGETTIMEOUTS)
-/*D*/ getTimeouts(&lockNow, NULL, NULL, NULL, NULL);
-
-    {
-      FILE *fp = fopen("/tmp/session", "a");
-      if (fp) fprintf(fp, "lockNow=%d saverTimeout=%d "
-                          "lockTimeout=%d cycleTimeout=%d"
-                          "saverList='%s'\n",
-                      lockNow, smSaverRes.saverTimeout,
-                      smSaverRes.lockTimeout, smSaverRes.cycleTimeout,
-                      smGD.saverList);
-      if (fp) fclose(fp);
-    }
-    #endif
-
    /*
     * coverScreen 
     *  0 - screen will not be covered, nor will external screen saver run
@@ -1589,6 +1670,97 @@ localAuthenticate(
       return FALSE;
 }
     
+#elif defined(linux)
+
+{
+    struct passwd *pwent = NULL;
+    char *p, *q;
+    char *crypt();
+    Boolean rc = True;
+    Boolean done = False;
+    struct spwd *sp = NULL;
+
+    if(smGD.secureSystem)
+    {  
+      SM_SETEUID(smGD.unLockUID);
+    }
+
+   /*
+    * Get password entry for 'name' or 'uid'.
+    */
+    if (CanReAuthenticate(name, uid, passwd, &pwent, &sp) == False)
+    {
+     /*
+      * Can't get entry.
+      */
+      rc = False;
+      done = True;
+    }
+
+    if(smGD.secureSystem)
+    {
+        SM_SETEUID(smGD.runningUID);
+    }
+
+    if (done == False)
+    {
+
+      if (pwent->pw_passwd == NULL || pwent->pw_passwd[0] == '*')
+      {
+                               /* check sp */
+       if (sp == NULL || sp->sp_pwdp == NULL)
+         {
+           /*
+            * Could not read password.
+            */
+           rc = False;
+           done = True;
+         }
+      }
+    }
+
+    if (done == False)
+    {
+      if (passwd == NULL)
+      {
+       /*
+        * Caller just checking if it is possible to access 
+        * password file (ie is dtsession suid bit set properly).
+        */
+        rc = True; 
+        done = True;
+      }
+    }
+
+    if (done == False)
+    {
+     /*
+      * Check password.
+      */
+
+      if (sp != NULL && !strcmp(sp->sp_pwdp, crypt(passwd,sp->sp_pwdp)))
+       {                       /* a shadow match */
+         rc = True;
+         done = True;
+       }
+      else if (pwent != NULL && 
+              !strcmp(pwent->pw_passwd, crypt(passwd, pwent->pw_passwd)))
+       {                       /* passwd match */
+         rc = True;
+          done = True;
+       }
+      else
+       {                       /* failure dude! */
+         rc = False;
+          done = True;
+       }
+    }
+
+    endpwent();
+    endspent();
+
+    return(rc);
+}
 
 #else
 
index 52a8ca9a3744307b3e7c96377592e050295de48f..9a864d6130ae4412232c04821438ceb4db9d2d91 100644 (file)
@@ -82,7 +82,6 @@
 /*
  * Internal Functions
  */
-void main(int, char **);
 static void StopAll(int i);
 static int RegisterX11ScreenSaver(Display *display, int *ssEventType);
 
@@ -125,9 +124,8 @@ static int RegisterX11ScreenSaver(Display *display, int *ssEventType);
  *  --------
  *
  *************************************<->***********************************/
-void
-main (int argc,
-          char  **argv)
+int
+main (int argc, char **argv)
 {
     int                         n, tmp;
     Arg                         args[10];
@@ -205,21 +203,22 @@ main (int argc,
      */
     smGD.runningUID = getuid();
 
-#ifdef SECURE_SYS_PATH
-    status = stat(SECURE_SYS_PATH, &buf);
-#else
-    status = -1;
-#endif
+#ifdef linux                   /* linux always needs to be setup as secure */
 
     /*
-     * Initialize LANG if it isn't defined.
+     * Save the root priviledge to be restored when trying to unlock
      */
-    if ((lang = getenv ("LANG")) == NULL)
-    {
-       lang = XtMalloc (7);
-       (void) strcpy (lang, "LANG=C");
-       (void) putenv (lang);
-    }
+    smGD.unLockUID = geteuid();
+    smGD.secureSystem = True;
+    SM_SETEUID(smGD.runningUID);
+    
+#else
+
+# ifdef SECURE_SYS_PATH
+    status = stat(SECURE_SYS_PATH, &buf);
+# else
+    status = -1;
+# endif
 
     if(status == -1)
     {
@@ -240,6 +239,18 @@ main (int argc,
         SM_SETEUID(smGD.runningUID);
     }
 
+#endif /* linux */
+
+    /*
+     * Initialize LANG if it isn't defined.
+     */
+    if ((lang = getenv ("LANG")) == NULL)
+    {
+       lang = XtMalloc (7);
+       (void) strcpy (lang, "LANG=C");
+       (void) putenv (lang);
+    }
+
 #ifdef __hpux
     setresgid(-1, smGD.runningGID, -1);
 #else  /* _AIX or any other system */
@@ -445,7 +456,7 @@ main (int argc,
     /*
      * Restore resources for lang/resolution independence
      */
-    if((smGD.resourcePath[0] != NULL) || (smGD.compatMode == False))
+    if((smGD.resourcePath[0] != 0) || (smGD.compatMode == False))
     {
        RestoreIndependentResources();
     }
@@ -453,7 +464,7 @@ main (int argc,
     /*
      * Now restore the rest of the clients and the settings
      */
-    if((smGD.clientPath[0] != NULL) && (smGD.compatMode == False))
+    if((smGD.clientPath[0] != 0) && (smGD.compatMode == False))
     {
        if(RestoreState() == -1)
        {