(root)/
Linux-PAM-1.5.3/
examples/
xsh.c
       1  /* Andrew Morgan (morgan@kernel.org) -- an example application
       2   * that invokes a shell, based on blank.c */
       3  
       4  #include "config.h"
       5  
       6  #include <stdio.h>
       7  #include <stdlib.h>
       8  
       9  #include <security/pam_appl.h>
      10  #include <security/pam_misc.h>
      11  
      12  #include <pwd.h>
      13  #include <sys/types.h>
      14  #include <unistd.h>
      15  
      16  /* ------ some local (static) functions ------- */
      17  
      18  static void bail_out(pam_handle_t *pamh,int really, int code, const char *fn)
      19  {
      20       fprintf(stderr,"==> called %s()\n  got: `%s'\n", fn,
      21  	     pam_strerror(pamh,code));
      22       if (really && code)
      23  	  exit (1);
      24  }
      25  
      26  /* ------ some static data objects ------- */
      27  
      28  static struct pam_conv conv = {
      29       misc_conv,
      30       NULL
      31  };
      32  
      33  /* ------- the application itself -------- */
      34  
      35  int main(int argc, char **argv)
      36  {
      37       pam_handle_t *pamh=NULL;
      38       const void *username=NULL;
      39       const char *service="xsh";
      40       int retcode;
      41  
      42       /* did the user call with a username as an argument ?
      43        * did they also */
      44  
      45       if (argc > 3) {
      46  	  fprintf(stderr,"usage: %s [username [service-name]]\n",argv[0]);
      47       }
      48       if ((argc >= 2) && (argv[1][0] != '-')) {
      49  	  username = argv[1];
      50       }
      51       if (argc == 3) {
      52  	 service = argv[2];
      53       }
      54  
      55       /* initialize the Linux-PAM library */
      56       retcode = pam_start(service, username, &conv, &pamh);
      57       bail_out(pamh,1,retcode,"pam_start");
      58  
      59       /* fill in the RUSER and RHOST etc. fields */
      60       {
      61  	 char buffer[100];
      62  	 struct passwd *pw;
      63  	 const char *tty;
      64  
      65  	 pw = getpwuid(getuid());
      66  	 if (pw != NULL) {
      67  	     retcode = pam_set_item(pamh, PAM_RUSER, pw->pw_name);
      68  	     bail_out(pamh,1,retcode,"pam_set_item(PAM_RUSER)");
      69  	 }
      70  
      71  	 retcode = gethostname(buffer, sizeof(buffer)-1);
      72  	 if (retcode) {
      73  	     perror("failed to look up hostname");
      74  	     retcode = pam_end(pamh, PAM_ABORT);
      75  	     bail_out(pamh,1,retcode,"pam_end");
      76  	 }
      77  	 retcode = pam_set_item(pamh, PAM_RHOST, buffer);
      78  	 bail_out(pamh,1,retcode,"pam_set_item(PAM_RHOST)");
      79  
      80  	 tty = ttyname(fileno(stdin));
      81  	 if (tty) {
      82  	     retcode = pam_set_item(pamh, PAM_TTY, tty);
      83  	     bail_out(pamh,1,retcode,"pam_set_item(PAM_TTY)");
      84  	 }
      85       }
      86  
      87       /* to avoid using goto we abuse a loop here */
      88       for (;;) {
      89  	  /* authenticate the user --- `0' here, could have been PAM_SILENT
      90  	   *	| PAM_DISALLOW_NULL_AUTHTOK */
      91  
      92  	  retcode = pam_authenticate(pamh, 0);
      93  	  bail_out(pamh,0,retcode,"pam_authenticate");
      94  
      95  	  /* has the user proved themself valid? */
      96  	  if (retcode != PAM_SUCCESS) {
      97  	       fprintf(stderr,"%s: invalid request\n",argv[0]);
      98  	       break;
      99  	  }
     100  
     101  	  /* the user is valid, but should they have access at this
     102  	     time? */
     103  
     104  	  retcode = pam_acct_mgmt(pamh, 0); /* `0' could be as above */
     105  	  bail_out(pamh,0,retcode,"pam_acct_mgmt");
     106  
     107  	  if (retcode == PAM_NEW_AUTHTOK_REQD) {
     108  	       fprintf(stderr,"Application must request new password...\n");
     109  	       retcode = pam_chauthtok(pamh,PAM_CHANGE_EXPIRED_AUTHTOK);
     110  	       bail_out(pamh,0,retcode,"pam_chauthtok");
     111  	  }
     112  
     113  	  if (retcode != PAM_SUCCESS) {
     114  	       fprintf(stderr,"%s: invalid request\n",argv[0]);
     115  	       break;
     116  	  }
     117  
     118  	  /* `0' could be as above */
     119  	  retcode = pam_setcred(pamh, PAM_ESTABLISH_CRED);
     120  	  bail_out(pamh,0,retcode,"pam_setcred");
     121  
     122  	  if (retcode != PAM_SUCCESS) {
     123  	       fprintf(stderr,"%s: problem setting user credentials\n"
     124  		       ,argv[0]);
     125  	       break;
     126  	  }
     127  
     128  	  /* open a session for the user --- `0' could be PAM_SILENT */
     129  	  retcode = pam_open_session(pamh,0);
     130  	  bail_out(pamh,0,retcode,"pam_open_session");
     131  	  if (retcode != PAM_SUCCESS) {
     132  	       fprintf(stderr,"%s: problem opening a session\n",argv[0]);
     133  	       break;
     134  	  }
     135  
     136  	  pam_get_item(pamh, PAM_USER, &username);
     137  	  fprintf(stderr,
     138  		  "The user [%s] has been authenticated and `logged in'\n",
     139  		  (const char *)username);
     140  
     141  	  /* this is always a really bad thing for security! */
     142  	  retcode = system("/bin/sh");
     143  
     144  	  /* close a session for the user --- `0' could be PAM_SILENT
     145  	   * it is possible that this pam_close_call is in another program..
     146  	   */
     147  
     148  	  retcode = pam_close_session(pamh,0);
     149  	  bail_out(pamh,0,retcode,"pam_close_session");
     150  	  if (retcode != PAM_SUCCESS) {
     151  	       fprintf(stderr,"%s: problem closing a session\n",argv[0]);
     152  	       break;
     153  	  }
     154  
     155  	  /* `0' could be as above */
     156  	  retcode = pam_setcred(pamh, PAM_DELETE_CRED);
     157  	  bail_out(pamh,0,retcode,"pam_setcred");
     158  	  if (retcode != PAM_SUCCESS) {
     159  	       fprintf(stderr,"%s: problem deleting user credentials\n"
     160  		       ,argv[0]);
     161  	       break;
     162  	  }
     163  
     164  	  break;                      /* don't go on for ever! */
     165       }
     166  
     167       /* close the Linux-PAM library */
     168       retcode = pam_end(pamh, PAM_SUCCESS);
     169       pamh = NULL;
     170       bail_out(pamh,1,retcode,"pam_end");
     171  
     172       return (0);
     173  }