コード例 #1
0
ファイル: pam_lastlog.c プロジェクト: tizenorg/toolchains.pam
static int
last_login_write(pam_handle_t *pamh, int announce, int last_fd,
		 uid_t uid, const char *user)
{
    struct flock last_lock;
    struct lastlog last_login;
    time_t ll_time;
    const void *void_remote_host = NULL;
    const char *remote_host;
    const char *terminal_line;
    int retval = PAM_SUCCESS;

    /* rewind */
    if (lseek(last_fd, sizeof(last_login) * (off_t) uid, SEEK_SET) < 0) {
	pam_syslog(pamh, LOG_ERR, "failed to lseek %s: %m", _PATH_LASTLOG);
	return PAM_SERVICE_ERR;
    }

    /* set this login date */
    D(("set the most recent login time"));
    (void) time(&ll_time);    /* set the time */
    last_login.ll_time = ll_time;

    /* set the remote host */
    if (pam_get_item(pamh, PAM_RHOST, &void_remote_host) != PAM_SUCCESS
	|| void_remote_host == NULL) {
	remote_host = DEFAULT_HOST;
    } else {
	remote_host = void_remote_host;
    }

    /* copy to last_login */
    last_login.ll_host[0] = '\0';
    strncat(last_login.ll_host, remote_host, sizeof(last_login.ll_host)-1);

    /* set the terminal line */
    terminal_line = get_tty(pamh);

    /* copy to last_login */
    last_login.ll_line[0] = '\0';
    strncat(last_login.ll_line, terminal_line, sizeof(last_login.ll_line)-1);
    terminal_line = NULL;

    D(("locking lastlog file"));

    /* now we try to lock this file-record exclusively; non-blocking */
    memset(&last_lock, 0, sizeof(last_lock));
    last_lock.l_type = F_WRLCK;
    last_lock.l_whence = SEEK_SET;
    last_lock.l_start = sizeof(last_login) * (off_t) uid;
    last_lock.l_len = sizeof(last_login);

    if (fcntl(last_fd, F_SETLK, &last_lock) < 0) {
	D(("locking %s failed..(waiting a little)", _PATH_LASTLOG));
	pam_syslog(pamh, LOG_WARNING, "file %s is locked/write", _PATH_LASTLOG);
        sleep(LASTLOG_IGNORE_LOCK_TIME);
    }

    D(("writing to the lastlog file"));
    if (pam_modutil_write (last_fd, (char *) &last_login,
			   sizeof (last_login)) != sizeof(last_login)) {
	pam_syslog(pamh, LOG_ERR, "failed to write %s: %m", _PATH_LASTLOG);
	retval = PAM_SERVICE_ERR;
    }

    last_lock.l_type = F_UNLCK;
    (void) fcntl(last_fd, F_SETLK, &last_lock);        /* unlock */
    D(("unlocked"));

    if (announce & LASTLOG_WTMP) {
	/* write wtmp entry for user */
	logwtmp(last_login.ll_line, user, remote_host);
    }

    /* cleanup */
    memset(&last_login, 0, sizeof(last_login));

    return retval;
}
コード例 #2
0
static int _unix_run_update_binary(pam_handle_t *pamh, unsigned int ctrl, const char *user,
    const char *fromwhat, const char *towhat, int remember)
{
    int retval, child, fds[2];
    struct sigaction newsa, oldsa;

    D(("called."));
    /* create a pipe for the password */
    if (pipe(fds) != 0) {
	D(("could not make pipe"));
	return PAM_AUTH_ERR;
    }

    if (off(UNIX_NOREAP, ctrl)) {
	/*
	 * This code arranges that the demise of the child does not cause
	 * the application to receive a signal it is not expecting - which
	 * may kill the application or worse.
	 *
	 * The "noreap" module argument is provided so that the admin can
	 * override this behavior.
	 */
        memset(&newsa, '\0', sizeof(newsa));
        newsa.sa_handler = SIG_DFL;
        sigaction(SIGCHLD, &newsa, &oldsa);
    }

    /* fork */
    child = fork();
    if (child == 0) {
        int i=0;
        struct rlimit rlim;
	static char *envp[] = { NULL };
	char *args[] = { NULL, NULL, NULL, NULL, NULL, NULL };
        char buffer[16];

	/* XXX - should really tidy up PAM here too */

	/* reopen stdin as pipe */
	dup2(fds[0], STDIN_FILENO);

	if (getrlimit(RLIMIT_NOFILE,&rlim)==0) {
	  if (rlim.rlim_max >= MAX_FD_NO)
	    rlim.rlim_max = MAX_FD_NO;
	  for (i=0; i < (int)rlim.rlim_max; i++) {
	    if (i != STDIN_FILENO)
	  	   close(i);
	  }
	}

	/* exec binary helper */
	args[0] = x_strdup(UPDATE_HELPER);
	args[1] = x_strdup(user);
	args[2] = x_strdup("update");
	if (on(UNIX_SHADOW, ctrl))
		args[3] = x_strdup("1");
	else
		args[3] = x_strdup("0");

        snprintf(buffer, sizeof(buffer), "%d", remember);
        args[4] = x_strdup(buffer);

	execve(UPDATE_HELPER, args, envp);

	/* should not get here: exit with error */
	D(("helper binary is not available"));
	_exit(PAM_AUTHINFO_UNAVAIL);
    } else if (child > 0) {
	/* wait for child */
	/* if the stored password is NULL */
        int rc=0;
	if (fromwhat)
	  pam_modutil_write(fds[1], fromwhat, strlen(fromwhat)+1);
	else
	  pam_modutil_write(fds[1], "", 1);
	if (towhat) {
	  pam_modutil_write(fds[1], towhat, strlen(towhat)+1);
	}
	else
	  pam_modutil_write(fds[1], "", 1);

	close(fds[0]);       /* close here to avoid possible SIGPIPE above */
	close(fds[1]);
	rc=waitpid(child, &retval, 0);  /* wait for helper to complete */
	if (rc<0) {
	  pam_syslog(pamh, LOG_ERR, "unix_update waitpid failed: %m");
	  retval = PAM_AUTHTOK_ERR;
	} else if (!WIFEXITED(retval)) {
          pam_syslog(pamh, LOG_ERR, "unix_update abnormal exit: %d", retval);
          retval = PAM_AUTHTOK_ERR;
        } else {
	  retval = WEXITSTATUS(retval);
	}
    } else {
	D(("fork failed"));
	close(fds[0]);
 	close(fds[1]);
	retval = PAM_AUTH_ERR;
    }

    if (off(UNIX_NOREAP, ctrl)) {
        sigaction(SIGCHLD, &oldsa, NULL);   /* restore old signal handler */
    }

    return retval;
}
コード例 #3
0
ファイル: mkhomedir_helper.c プロジェクト: DTherHtun/testwork
/* Do the actual work of creating a home dir */
static int
create_homedir(const struct passwd *pwd,
	       const char *source, const char *dest)
{
   char remark[BUFSIZ];
   DIR *d;
   struct dirent *dent;
   int retval = PAM_SESSION_ERR;

   /* Create the new directory */
   if (rec_mkdir(dest, 0755) != 0)
   {
      pam_syslog(NULL, LOG_ERR, "unable to create directory %s: %m", dest);
      return PAM_PERM_DENIED;
   }

   /* See if we need to copy the skel dir over. */
   if ((source == NULL) || (strlen(source) == 0))
   {
      retval = PAM_SUCCESS;
      goto go_out;
   }

   /* Scan the directory */
   d = opendir(source);
   if (d == NULL)
   {
      pam_syslog(NULL, LOG_DEBUG, "unable to read directory %s: %m", source);
      retval = PAM_PERM_DENIED;
      goto go_out;
   }

   for (dent = readdir(d); dent != NULL; dent = readdir(d))
   {
      int srcfd;
      int destfd;
      int res;
      struct stat st;
#ifndef PATH_MAX
      char *newsource = NULL, *newdest = NULL;
      /* track length of buffers */
      int nslen = 0, ndlen = 0;
      int slen = strlen(source), dlen = strlen(dest);
#else
      char newsource[PATH_MAX], newdest[PATH_MAX];
#endif

      /* Skip some files.. */
      if (strcmp(dent->d_name,".") == 0 ||
	  strcmp(dent->d_name,"..") == 0)
	 continue;

      /* Determine what kind of file it is. */
#ifndef PATH_MAX
      nslen = slen + strlen(dent->d_name) + 2;

      if (nslen <= 0)
	{
	  retval = PAM_BUF_ERR;
	  goto go_out;
	}

      if ((newsource = malloc(nslen)) == NULL)
	{
	  retval = PAM_BUF_ERR;
	  goto go_out;
	}

      sprintf(newsource, "%s/%s", source, dent->d_name);
#else
      snprintf(newsource, sizeof(newsource), "%s/%s", source, dent->d_name);
#endif

      if (lstat(newsource, &st) != 0)
#ifndef PATH_MAX
      {
	      free(newsource);
	      newsource = NULL;
         continue;
      }
#else
      continue;
#endif


      /* We'll need the new file's name. */
#ifndef PATH_MAX
      ndlen = dlen + strlen(dent->d_name)+2;

      if (ndlen <= 0)
	{
	  retval = PAM_BUF_ERR;
	  goto go_out;
	}

      if ((newdest = malloc(ndlen)) == NULL)
	{
	  free (newsource);
	  retval = PAM_BUF_ERR;
	  goto go_out;
	}

      sprintf (newdest, "%s/%s", dest, dent->d_name);
#else
      snprintf (newdest, sizeof (newdest), "%s/%s", dest, dent->d_name);
#endif

      /* If it's a directory, recurse. */
      if (S_ISDIR(st.st_mode))
      {
         retval = create_homedir(pwd, newsource, newdest);

#ifndef PATH_MAX
	 free(newsource); newsource = NULL;
	 free(newdest); newdest = NULL;
#endif

         if (retval != PAM_SUCCESS)
	   {
	     closedir(d);
	     goto go_out;
	   }
         continue;
      }

      /* If it's a symlink, create a new link. */
      if (S_ISLNK(st.st_mode))
      {
	 int pointedlen = 0;
#ifndef PATH_MAX
	 char *pointed = NULL;
           {
		   int size = 100;

		   while (1) {
			   pointed = malloc(size);
			   if (pointed == NULL) {
				   free(newsource);
				   free(newdest);
				   return PAM_BUF_ERR;
			   }
			   pointedlen = readlink(newsource, pointed, size);
			   if (pointedlen < 0) break;
			   if (pointedlen < size) break;
			   free(pointed);
			   size *= 2;
		   }
	   }
	   if (pointedlen < 0)
		   free(pointed);
	   else
		   pointed[pointedlen] = 0;
#else
         char pointed[PATH_MAX];
         memset(pointed, 0, sizeof(pointed));

         pointedlen = readlink(newsource, pointed, sizeof(pointed) - 1);
#endif

	 if (pointedlen >= 0) {
            if(symlink(pointed, newdest) == 0)
            {
               if (lchown(newdest, pwd->pw_uid, pwd->pw_gid) != 0)
               {
                   pam_syslog(NULL, LOG_DEBUG,
			      "unable to change perms on link %s: %m", newdest);
                   closedir(d);
#ifndef PATH_MAX
		   free(pointed);
		   free(newsource);
		   free(newdest);
#endif
                   return PAM_PERM_DENIED;
               }
            }
#ifndef PATH_MAX
	    free(pointed);
#endif
         }
#ifndef PATH_MAX
	 free(newsource); newsource = NULL;
	 free(newdest); newdest = NULL;
#endif
         continue;
      }

      /* If it's not a regular file, it's probably not a good idea to create
       * the new device node, FIFO, or whatever it is. */
      if (!S_ISREG(st.st_mode))
      {
#ifndef PATH_MAX
	 free(newsource); newsource = NULL;
	 free(newdest); newdest = NULL;
#endif
         continue;
      }

      /* Open the source file */
      if ((srcfd = open(newsource, O_RDONLY)) < 0 || fstat(srcfd, &st) != 0)
      {
         pam_syslog(NULL, LOG_DEBUG,
		    "unable to open src file %s: %m", newsource);
         closedir(d);

#ifndef PATH_MAX
	 free(newsource); newsource = NULL;
	 free(newdest); newdest = NULL;
#endif

	 return PAM_PERM_DENIED;
      }
      if (stat(newsource, &st) != 0)
	{
	  pam_syslog(NULL, LOG_DEBUG, "unable to stat src file %s: %m",
		     newsource);
	  close(srcfd);
	  closedir(d);

#ifndef PATH_MAX
	  free(newsource); newsource = NULL;
	  free(newdest); newdest = NULL;
#endif

	  return PAM_PERM_DENIED;
	}

      /* Open the dest file */
      if ((destfd = open(newdest, O_WRONLY | O_TRUNC | O_CREAT, 0600)) < 0)
      {
         pam_syslog(NULL, LOG_DEBUG,
		    "unable to open dest file %s: %m", newdest);
	 close(srcfd);
	 closedir(d);

#ifndef PATH_MAX
	 free(newsource); newsource = NULL;
	 free(newdest); newdest = NULL;
#endif
	 return PAM_PERM_DENIED;
      }

      /* Set the proper ownership and permissions for the module. We make
       	 the file a+w and then mask it with the set mask. This preseves
       	 execute bits */
      if (fchmod(destfd, (st.st_mode | 0222) & (~u_mask)) != 0 ||
	  fchown(destfd, pwd->pw_uid, pwd->pw_gid) != 0)
      {
         pam_syslog(NULL, LOG_DEBUG,
		    "unable to change perms on copy %s: %m", newdest);
         close(srcfd);
         close(destfd);
         closedir(d);

#ifndef PATH_MAX
	 free(newsource); newsource = NULL;
	 free(newdest); newdest = NULL;
#endif

	 return PAM_PERM_DENIED;
      }

      /* Copy the file */
      do
      {
	 res = pam_modutil_read(srcfd, remark, sizeof(remark));

	 if (res == 0)
	     continue;

	 if (res > 0) {
	     if (pam_modutil_write(destfd, remark, res) == res)
		continue;
	 }

	 /* If we get here, pam_modutil_read returned a -1 or
	    pam_modutil_write returned something unexpected. */
	 pam_syslog(NULL, LOG_DEBUG, "unable to perform IO: %m");
	 close(srcfd);
	 close(destfd);
	 closedir(d);

#ifndef PATH_MAX
	 free(newsource); newsource = NULL;
	 free(newdest); newdest = NULL;
#endif

	 return PAM_PERM_DENIED;
      }
      while (res != 0);
      close(srcfd);
      close(destfd);

#ifndef PATH_MAX
      free(newsource); newsource = NULL;
      free(newdest); newdest = NULL;
#endif

   }
   closedir(d);

   retval = PAM_SUCCESS;

 go_out:

   if (chmod(dest, 0777 & (~u_mask)) != 0 ||
       chown(dest, pwd->pw_uid, pwd->pw_gid) != 0)
   {
      pam_syslog(NULL, LOG_DEBUG,
		 "unable to change perms on directory %s: %m", dest);
      return PAM_PERM_DENIED;
   }

   return retval;
}