mod_pam.c
上传用户:pycemail
上传日期:2007-01-04
资源大小:329k
文件大小:8k
源码类别:

Ftp客户端

开发平台:

Unix_Linux

  1. /*
  2.  * ProFTPD: mod_pam -- Support for PAM-style authentication.
  3.  * Time-stamp: <1998-10-19 1:03:02 macgyver>
  4.  * Copyright (c) 1998 Habeeb J. Dihu aka MacGyver <macgyver@tos.net>,
  5.  *  All Rights Reserved.
  6.  *  
  7.  * This program is free software; you can redistribute it and/or modify
  8.  * it under the terms of the GNU General Public License as published by
  9.  * the Free Software Foundation; either version 2 of the License, or
  10.  * (at your option) any later version.
  11.  *
  12.  * This program is distributed in the hope that it will be useful,
  13.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.  * GNU General Public License for more details.
  16.  *
  17.  * You should have received a copy of the GNU General Public License
  18.  * along with this program; if not, write to the Free Software
  19.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA.
  20.  */
  21. /*
  22.  * PAM module from ProFTPD
  23.  *
  24.  * This module should work equally well under all Linux distributions (which
  25.  * have PAM support), as well as Solaris 2.5 and above.
  26.  *
  27.  * If you have any problems, questions, comments, or suggestions regarding
  28.  * this module, please feel free to contact Habeeb J. Dihu aka MacGyver
  29.  * <macgyver@tos.net>.
  30.  *
  31.  * -- DO NOT MODIFY THE TWO LINES BELOW --
  32.  * $Libraries: -lpam$
  33.  * $Id: mod_pam.c,v 1.2 1999/09/17 07:31:44 macgyver Exp $
  34.  * $Log: mod_pam.c,v $
  35.  * Revision 1.2  1999/09/17 07:31:44  macgyver
  36.  * Implemented sstrncpy to handle proper buffer copying issues on all platforms.
  37.  *
  38.  * Revision 1.1  1999/09/10 20:17:18  macgyver
  39.  * Moved PAM into the main module set.  It's now a 'core' feature.
  40.  *
  41.  * Revision 1.4  1999/09/08 08:35:35  macgyver
  42.  * Updates to auto-configuring for PAM on *BSD.
  43.  *
  44.  * Revision 1.3  1999/09/07 23:13:14  macgyver
  45.  * Some minor security updates to fix potential buffer problems.
  46.  *
  47.  * Revision 1.2  1999/03/05 03:34:12  flood
  48.  * MacGyver's patch to do argv[] rewriting the Right Way<tm>, and some minor
  49.  * socket error handling fixes.
  50.  *
  51.  * Revision 1.1  1998/11/01 19:08:21  flood
  52.  * APPE, mod_pam & mod_readme added
  53.  *
  54.  * Revision 1.6  1998/10/26 06:47:35  macgyver
  55.  * Reworked configuration handling to be 1.2 compliant.
  56.  *
  57.  * Revision 1.5  1998/10/23 04:25:45  macgyver
  58.  * Changed configuration parameter to AuthPAMAuthoritative to be more in tune
  59.  * with Apache.  Credit to Jay Soffian for the suggestion.
  60.  *
  61.  * Revision 1.4  1998/10/22 04:25:09  macgyver
  62.  * Updated for CVS.
  63.  *
  64.  */
  65. #include "conf.h"
  66. #include "privs.h"
  67. #include <security/pam_appl.h>
  68. static char *  pam_user  = (char *)0;
  69. static char *  pam_pass  = (char *)0;
  70. static int  pam_conv_error = 0;
  71. static int pam_exchange(num_msg, msg, resp, appdata_ptr)
  72.      int num_msg;
  73.      struct pam_message **msg;
  74.      struct pam_response **resp;
  75.      void *appdata_ptr;
  76. {
  77.   int i;
  78.   struct pam_response *response = NULL;
  79.   
  80.   response = malloc(sizeof(struct pam_response) * num_msg);
  81.   if(response == (struct pam_response *)0)
  82.     return PAM_CONV_ERR;
  83.   
  84.   for(i = 0; i < num_msg; i++) {
  85.     response[i].resp_retcode = PAM_SUCCESS;
  86.     
  87.     switch(msg[i]->msg_style) {
  88.     case PAM_PROMPT_ECHO_ON:
  89.       response[i].resp = pam_user;
  90.       /* PAM frees resp */
  91.       break;
  92.       
  93.     case PAM_PROMPT_ECHO_OFF:
  94.       response[i].resp = pam_pass;
  95.       /* PAM frees resp */
  96.       break;
  97.       
  98.     case PAM_TEXT_INFO:
  99.     case PAM_ERROR_MSG:
  100.       /* ignore it, but pam still wants a NULL response... */
  101.       response[i].resp = NULL;
  102.       break;
  103.       
  104.     default:
  105.       /* Must be an error of some sort... */
  106.       free(response);
  107.       pam_conv_error = 1;
  108.       return PAM_CONV_ERR;
  109.     }
  110.   }
  111.   
  112.   *resp = response;
  113.   return PAM_SUCCESS;
  114. }
  115. static struct pam_conv pam_conv = {
  116.   &pam_exchange,
  117.   NULL
  118. };
  119. MODRET pam_auth(cmd_rec *cmd)
  120. {
  121.   int pam_error = 0, retval = 0, pam_return_type;
  122.   int success = 0;
  123.   pam_handle_t *pamh = NULL;
  124.   config_rec *c;
  125.   char *pamconfig = "ftp";
  126.   
  127.   /* Figure out our default return style:
  128.    * Whether or not PAM should allow other auth modules a shot at this
  129.    * user or not is controlled by the parameter
  130.    * "AuthPAMAuthoritative".  It defaults to no, since it is a more
  131.    * closed (read secure) environment.
  132.    */
  133.   pam_return_type = get_param_int(TOPLEVEL_CONF,
  134.                                   "AuthPAMAuthoritative", FALSE);
  135.     
  136.   /* Just in case...
  137.    */
  138.   if(cmd->argc != 2)
  139.     return pam_return_type ? ERROR(cmd) : DECLINED(cmd);
  140.   
  141.   /* Allocate our entries...we don't free this because PAM does this for us.
  142.    */
  143.   pam_user = malloc(strlen(cmd->argv[0]) + 1);
  144.   if(pam_user == (char *)0)
  145.     return pam_return_type ? ERROR(cmd) : DECLINED(cmd);
  146.   sstrncpy(pam_user, cmd->argv[0], strlen(cmd->argv[0]) + 1);
  147.   
  148.   pam_pass = malloc(strlen(cmd->argv[1]) + 1);
  149.   if(pam_pass == (char *)0)
  150.     return pam_return_type ? ERROR(cmd) : DECLINED(cmd);
  151.   sstrncpy(pam_pass, cmd->argv[1], strlen(cmd->argv[1]) + 1);
  152.   
  153.   /* Check for which PAM config file to use.  Since we have many different
  154.    * potential servers, they may each require a seperate type of PAM
  155.    * authentication.
  156.    */
  157.   if((c = find_config(TOPLEVEL_CONF, CONF_PARAM, "PAMConfig", FALSE)) != NULL)
  158.     pamconfig = c->argv[0];
  159.   
  160.   /* Due to the different types of authentication used, such as shadow
  161.    * passwords, etc. we need root privs for this operation.
  162.    */
  163.   block_signals();
  164.   PRIVS_ROOT
  165.   pam_error = pam_start(pamconfig, pam_user, &pam_conv, &pamh);
  166.   if(pam_error != PAM_SUCCESS)
  167.     goto done;
  168.   
  169.   /* Authenticate, and get any credentials as needed.
  170.    */
  171.   pam_error = pam_authenticate(pamh, PAM_SILENT);
  172.   
  173.   if(pam_error != PAM_SUCCESS) {
  174.     switch(pam_error) {
  175.     case PAM_USER_UNKNOWN:
  176.       retval = AUTH_NOPWD;
  177.       break;
  178.       
  179.     default:
  180.       retval = AUTH_BADPWD;
  181.       break;
  182.     }
  183.     
  184.     log_pri(LOG_NOTICE, "PAM(%s): %s", cmd->argv[0],
  185.     pam_strerror(pamh, pam_error));
  186.     goto done;
  187.   }
  188.   
  189.   if(pam_conv_error != 0) {
  190.     retval = AUTH_BADPWD;
  191.     goto done;
  192.   }
  193.   
  194.   pam_error = pam_acct_mgmt(pamh, PAM_SILENT);
  195.   if(pam_error != PAM_SUCCESS) {
  196.     switch(pam_error) {
  197. #ifdef PAM_AUTHTOKEN_REQD
  198.     case PAM_AUTHTOKEN_REQD:
  199.       retval = AUTH_AGEPWD;
  200.       break;
  201. #endif /* PAM_AUTHTOKEN_REQD */
  202.     case PAM_ACCT_EXPIRED:
  203.       retval = AUTH_DISABLEDPWD;
  204.       break;
  205.       
  206.     case PAM_USER_UNKNOWN:
  207.       retval = AUTH_NOPWD;
  208.       break;
  209.       
  210.     default:
  211.       retval = AUTH_BADPWD;
  212.       break;
  213.     }
  214.     
  215.     log_pri(LOG_NOTICE, "PAM(%s): %s", cmd->argv[0],
  216.     pam_strerror(pamh, pam_error));
  217.     goto done;
  218.   }
  219.   
  220.   pam_error = pam_setcred(pamh, PAM_ESTABLISH_CRED);
  221.   
  222.   if(pam_error != PAM_SUCCESS) {
  223.     switch(pam_error) {
  224.     case PAM_CRED_EXPIRED:
  225.       retval = AUTH_AGEPWD;
  226.       break;
  227.       
  228.     case PAM_USER_UNKNOWN:
  229.       retval = AUTH_NOPWD;
  230.       break;
  231.       
  232.     default:
  233.       retval = AUTH_BADPWD;
  234.       break;
  235.     }
  236.     
  237.     log_pri(LOG_NOTICE, "PAM(%s): %s", cmd->argv[0],
  238.     pam_strerror(pamh, pam_error));
  239.     goto done;
  240.   }
  241.   
  242.   success++;
  243.   
  244.  done:
  245.   /* And we're done.  Close off any PAM pointers, and relinquish our root
  246.    * privs.
  247.    */
  248.   pam_end(pamh, pam_error);
  249.   PRIVS_RELINQUISH;
  250.   unblock_signals();
  251.   
  252.   if(!success)
  253.     return pam_return_type ? ERROR_INT(cmd, retval) : DECLINED(cmd);
  254.   else
  255.     return HANDLED(cmd);
  256. }
  257. MODRET set_pamauthoritative(cmd_rec *cmd)
  258. {
  259.   int b;
  260.   
  261.   CHECK_ARGS(cmd, 1);
  262.   CHECK_CONF(cmd, CONF_ROOT);
  263.   
  264.   if((b = get_boolean(cmd, 1)) == -1)
  265.     CONF_ERROR(cmd, "expected boolean argument.");
  266.   add_config_param("AuthPAMAuthoritative", 1, (void *) b);
  267.   return HANDLED(cmd);
  268. }
  269. MODRET set_pamconfig(cmd_rec *cmd)
  270. {
  271.   CHECK_ARGS(cmd, 1);
  272.   CHECK_CONF(cmd, CONF_ROOT | CONF_VIRTUAL | CONF_ANON | CONF_GLOBAL);
  273.   add_config_param_str("PAMConfig", 1, (void *) cmd->argv[1]);
  274.   
  275.   return HANDLED(cmd);
  276. }
  277. static authtable pam_authtab[] = {
  278.   { 0, "auth", pam_auth},
  279.   { 0, NULL, NULL}
  280. };
  281. static conftable pam_conftab[] = {
  282.   { "AuthPAMAuthoritative", set_pamauthoritative, NULL },
  283.   { "PAMConfig", set_pamconfig, NULL },
  284.   { NULL, NULL, NULL}
  285. };
  286. module pam_module = {
  287.   NULL,NULL, /* Always NULL */
  288.   0x20, /* API Version 2.0 */
  289.   "pam",
  290.   pam_conftab, /* PAM configuration handler table */
  291.   NULL, /* No command handler table */
  292.   pam_authtab, /* PAM authentication handler table */
  293.   NULL,          /* No initialization needed */
  294.   NULL            /* No post-fork "child mode" init */
  295. };