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

Ftp客户端

开发平台:

Unix_Linux

  1. /*
  2.  * ProFTPD - FTP server daemon
  3.  * Copyright (c) 1997, 1998 Public Flood Software
  4.  *  
  5.  * This program is free software; you can redistribute it and/or modify
  6.  * it under the terms of the GNU General Public License as published by
  7.  * the Free Software Foundation; either version 2 of the License, or
  8.  * (at your option) any later version.
  9.  *
  10.  * This program is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  * GNU General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU General Public License
  16.  * along with this program; if not, write to the Free Software
  17.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA.
  18.  */
  19. /*
  20.  * unix password lookup module for ProFTPD
  21.  * $Id: mod_unixpw.c,v 1.3 1999/10/01 03:33:47 macgyver Exp $
  22.  */
  23. #include "conf.h"
  24. #ifdef HAVE_CRYPT_H
  25. #include <crypt.h>
  26. #endif
  27. #ifdef USESHADOW
  28. #include <shadow.h>
  29. #endif
  30. #ifdef HAVE_SYS_SECURITY_H
  31. #include <sys/security.h>
  32. #endif
  33. #ifdef HAVE_KRB_H
  34. #include <krb.h>
  35. #endif
  36. #ifdef HAVE_HPSECURITY_H
  37. #include <hpsecurity.h>
  38. #endif
  39. #ifdef HAVE_PROT_H
  40. #include <prot.h>
  41. #endif
  42. #include "privs.h"
  43. const char *pwdfname="/etc/passwd";
  44. const char *grpfname="/etc/group";
  45. #ifdef HAVE__PW_STAYOPEN
  46. extern int _pw_stayopen;
  47. #endif
  48. #define HASH_TABLE_SIZE 10
  49. typedef struct _idmap {
  50.   struct _idmap *next,*prev;
  51.   int id; /* uid or gid */
  52.   char *name; /* user or group name */
  53. } idmap_t;
  54. static xaset_t *uid_table[HASH_TABLE_SIZE];
  55. static xaset_t *gid_table[HASH_TABLE_SIZE];
  56. static FILE *pwdf = NULL;
  57. static FILE *grpf = NULL;
  58. #ifdef NEED_PERSISTENT_PASSWD
  59. int persistent = 1;
  60. #else
  61. int persistent = 0;
  62. #endif
  63. static int persistent_passwd = 0, persistent_group = 0;
  64. #define PERSISTENT_PASSWD (persistent || persistent_passwd)
  65. #define PERSISTENT_GROUP (persistent || persistent_group)
  66. #undef PASSWD
  67. #define PASSWD pwdfname
  68. #undef GROUP
  69. #define GROUP grpfname
  70. #ifdef USESHADOW
  71. /* Shadow password entries are stored as number of days, not seconds
  72.  * and are -1 if unused
  73.  */
  74. #define SP_CVT_DAYS(x) ((x) == (time_t)-1 ? (x) : ((x) * 86400))
  75. #endif /* USESHADOW */
  76. static void p_setpwent()
  77. {
  78.   if(pwdf)
  79.     rewind(pwdf);
  80.   else
  81.     pwdf = fopen(PASSWD,"r");
  82. }
  83. static void p_endpwent()
  84. {
  85.   if(pwdf) {
  86.     fclose(pwdf);
  87.     pwdf = NULL;
  88.   }
  89. }
  90. static void p_setgrent()
  91. {
  92.   if(grpf)
  93.     rewind(grpf);
  94.   else
  95.     grpf = fopen(GROUP,"r");
  96. }
  97. static void p_endgrent()
  98. {   
  99.   if(grpf) {
  100.     fclose(grpf);
  101.     grpf = NULL;
  102.   }
  103. }
  104. static struct passwd *p_getpwent()
  105. {  
  106.   if(!pwdf)
  107.     p_setpwent();
  108.   if(!pwdf)
  109.     return NULL;
  110.   
  111.   return fgetpwent(pwdf);
  112. }
  113. static struct group *p_getgrent()
  114. {   
  115.   struct group *gr;
  116.    
  117.   if(!grpf)
  118.     p_setgrent();
  119.   
  120.   if(!grpf)
  121.     return NULL;
  122.   gr = fgetgrent(grpf);  
  123.  
  124.   return gr;
  125. }
  126. static struct passwd *p_getpwnam(const char *name)
  127. {  
  128.   struct passwd *pw;
  129.     
  130.   p_setpwent();
  131.   while((pw = p_getpwent()) != NULL)
  132.     if(!strcmp(name,pw->pw_name))
  133.       break;
  134.  
  135.   return pw;
  136. }
  137. static struct passwd *p_getpwuid(uid_t uid)
  138. {   
  139.   struct passwd *pw;
  140.   
  141.   p_setpwent();
  142.   while((pw = p_getpwent()) != NULL)
  143.     if(pw->pw_uid == uid)
  144.       break;
  145.  
  146.   return pw;
  147. }
  148. static struct group *p_getgrnam(const char *name)
  149.   struct group *gr;
  150.   
  151.   p_setgrent();
  152.   while((gr = p_getgrent()) != NULL)
  153.     if(!strcmp(name,gr->gr_name))
  154.       break;
  155.  
  156.   return gr;
  157. }
  158. static struct group *p_getgrgid(gid_t gid)
  159.   struct group *gr;
  160.   
  161.   p_setgrent();
  162.   while((gr = p_getgrent()) != NULL)
  163.     if(gr->gr_gid == gid)
  164.       break;
  165.  
  166.   return gr;
  167. }
  168. static int _compare_id(idmap_t *m1, idmap_t *m2)
  169. {
  170.   if(m1->id < m2->id)
  171.     return -1;
  172.   if(m1->id > m2->id)
  173.     return 1;
  174.   return 0;
  175. }
  176. static idmap_t *_auth_lookup_id(xaset_t **id_table, int id)
  177. {
  178.   int hash = id % HASH_TABLE_SIZE;
  179.   idmap_t *m;
  180.   if(!id_table[hash])
  181.     id_table[hash] = xaset_create(permanent_pool,
  182.                      (XASET_COMPARE)_compare_id);
  183.   for(m = (idmap_t*)id_table[hash]->xas_list; m; m=m->next)
  184.     if(m->id == id)
  185.       break;
  186.   if(!m || m->id != id) {
  187.     /* Isn't in the table */
  188.     m = (idmap_t*)pcalloc(id_table[hash]->mempool,sizeof(idmap_t));
  189.     m->id = id;
  190.     xaset_insert_sort(id_table[hash],(xasetmember_t*)m,FALSE);
  191.   }
  192.   return m;
  193. }
  194. MODRET pw_setpwent(cmd_rec *cmd)
  195. {
  196.   if(PERSISTENT_PASSWD)
  197.     p_setpwent();
  198.   else
  199.     setpwent();
  200.   return HANDLED(cmd);
  201. }
  202. MODRET pw_endpwent(cmd_rec *cmd)
  203. {
  204.   if(PERSISTENT_PASSWD)
  205.     p_endpwent();
  206.   else
  207.     endpwent();
  208.   return HANDLED(cmd);
  209. }
  210. MODRET pw_setgrent(cmd_rec *cmd)
  211. {
  212.   if(PERSISTENT_GROUP)
  213.     p_setgrent();
  214.   else
  215.     setgrent();
  216.   return HANDLED(cmd);
  217. }
  218. MODRET pw_endgrent(cmd_rec *cmd)
  219. {
  220.   if(PERSISTENT_GROUP)
  221.     p_endgrent();
  222.   else
  223.     endgrent();
  224.   return HANDLED(cmd);
  225. }
  226. MODRET pw_getgrent(cmd_rec *cmd)
  227. {
  228.   struct group *gr;
  229.   if(PERSISTENT_GROUP)
  230.     gr = p_getgrent();
  231.   else
  232.     gr = getgrent();
  233.   if(gr)
  234.     return mod_create_data(cmd,gr);
  235.   else
  236.     return ERROR(cmd);
  237. }
  238. MODRET pw_getpwent(cmd_rec *cmd)
  239. {
  240.   struct passwd *pw;
  241.   if(PERSISTENT_PASSWD)
  242.     pw = p_getpwent();
  243.   else
  244.     pw = getpwent();
  245.   if(pw)
  246.     return mod_create_data(cmd,pw);
  247.   else
  248.     return ERROR(cmd);
  249. }
  250. MODRET pw_getpwuid(cmd_rec *cmd)
  251. {
  252.   struct passwd *pw;
  253.   uid_t uid;
  254.   uid = (uid_t)cmd->argv[0];
  255.   if(PERSISTENT_PASSWD)
  256.     pw = p_getpwuid(uid);
  257.   else
  258.     pw = getpwuid(uid);
  259.   if(pw)
  260.     return mod_create_data(cmd,pw);
  261.   else
  262.     return ERROR(cmd);
  263. }
  264. MODRET pw_getpwnam(cmd_rec *cmd)
  265. {
  266.   struct passwd *pw;
  267.   const char *name;
  268.   name = cmd->argv[0];
  269.   if(PERSISTENT_PASSWD)
  270.     pw = p_getpwnam(name);
  271.   else
  272.     pw = getpwnam(name);
  273.   if(pw)
  274.     return mod_create_data(cmd,pw);
  275.   else
  276.     return ERROR(cmd);
  277. }
  278. MODRET pw_getgrnam(cmd_rec *cmd)
  279. {
  280.   struct group *gr;
  281.   const char *name;
  282.   name = cmd->argv[0];
  283.   if(PERSISTENT_GROUP)
  284.     gr = p_getgrnam(name);
  285.   else
  286.     gr = getgrnam(name);
  287.   if(gr)
  288.     return mod_create_data(cmd,gr);
  289.   else
  290.     return ERROR(cmd);
  291. }
  292. MODRET pw_getgrgid(cmd_rec *cmd)
  293. {
  294.   struct group *gr;
  295.   gid_t gid;
  296.   gid = (gid_t)cmd->argv[0];
  297.   if(PERSISTENT_GROUP)
  298.     gr = p_getgrgid(gid);
  299.   else
  300.     gr = getgrgid(gid);
  301.   if(gr)
  302.     return mod_create_data(cmd,gr);
  303.   else
  304.     return ERROR(cmd);
  305. }
  306. #ifdef USESHADOW
  307. static char *_get_pw_info(pool *p, const char *u,
  308.                           time_t *lstchg, time_t *min, time_t *max,
  309.                           time_t *warn, time_t *inact, time_t *expire)
  310. {
  311.   struct spwd *sp;
  312.   char *cpw = NULL;
  313.   PRIVS_ROOT
  314.   sp = getspnam(u);
  315.   if(sp) {
  316.     cpw = pstrdup(p,sp->sp_pwdp);
  317.     if(lstchg) *lstchg = SP_CVT_DAYS(sp->sp_lstchg);
  318.     if(min) *min = SP_CVT_DAYS(sp->sp_min);
  319.     if(max) *max = SP_CVT_DAYS(sp->sp_max);
  320.     if(warn) *warn = SP_CVT_DAYS(sp->sp_warn);
  321.     if(inact) *inact = SP_CVT_DAYS(sp->sp_inact);
  322.     if(expire) *expire = SP_CVT_DAYS(sp->sp_expire);
  323.   }
  324. #ifdef AUTOSHADOW
  325.   else {
  326.     struct passwd *pw;
  327.     endspent();
  328.     PRIVS_RELINQUISH
  329.     if((pw = getpwnam(u)) != NULL) {
  330.       cpw = pstrdup(p,pw->pw_passwd);
  331.       if(lstchg) *lstchg = (time_t)-1;
  332.       if(min) *min = (time_t)-1;
  333.       if(max) *max = (time_t)-1;
  334.       if(warn) *warn = (time_t)-1;
  335.       if(inact) *inact = (time_t)-1;
  336.       if(expire) *expire = (time_t)-1;
  337.     }
  338.   }
  339. #else
  340.   endspent();
  341.   PRIVS_RELINQUISH
  342. #endif /* AUTOSHADOW */
  343.   return cpw;
  344. }
  345. #else /* USESHADOW */
  346. static char *_get_pw_info(pool *p, const char *u,
  347.                           time_t *lstchg, time_t *min, time_t *max,
  348.                           time_t *warn, time_t *inact, time_t *expire)
  349. {
  350.   char *cpw = NULL;
  351. #ifdef HAVE_GETPRPWENT
  352.   struct pr_passwd *pw;
  353. #else
  354.   struct passwd *pw;
  355. #endif
  356.  /* some platforms (i.e. bsd) provide "transparent" shadowing, which
  357.   * requires that we are root in order to have the password member
  358.   * filled in.
  359.   */
  360.   PRIVS_ROOT
  361. #ifndef HAVE_GETPRPWENT
  362.   endpwent();
  363. #if defined(BSDI3) || defined(BSDI4)
  364.   /* endpwent() seems to be buggy on BSDI3.1 (is this true for 4.0?)
  365.    * setpassent(0) _seems_ to do the same thing, however this conflicts
  366.    * with the man page documented behavior.  Argh, why do all the bsds
  367.    * have to be different in this area (except OpenBSD, grin).
  368.    */
  369.   setpassent(0);
  370. #else /* BSDI3 || BSDI4 */
  371.   setpwent();
  372. #endif /* BSDI3 || BSDI4 */
  373.   pw = getpwnam(u);
  374.   if(pw) {
  375.     cpw = pstrdup(p,pw->pw_passwd);
  376.     if(lstchg) *lstchg = (time_t)-1;
  377.     if(min) *min = (time_t)-1;
  378.     if(max) *max = (time_t)-1;
  379.     if(warn) *warn = (time_t)-1;
  380.     if(inact) *inact = (time_t)-1;
  381.     if(expire) *expire = (time_t)-1;
  382.   }
  383.   endpwent();
  384. #else /* HAVE_GETPRPWENT */
  385.   endprpwent();
  386.   setprpwent();
  387.   pw = getprpwnam(u);
  388.   if(pw) {
  389.     cpw = pstrdup(p,pw->ufld.fd_encrypt);
  390.     if(lstchg) *lstchg = (time_t)-1;
  391.     if(min) *min = pw->ufld.fd_min; 
  392.     if(max) *max = (time_t)-1;
  393.     if(warn) *warn = (time_t)-1;
  394.     if(inact) *inact = (time_t)-1;
  395.     if(expire) *expire = pw->ufld.fd_expire;
  396.   }
  397.   endprpwent();
  398. #endif /* HAVE_GETPRPWENT */
  399.   PRIVS_RELINQUISH
  400. #if defined(BSDI3) || defined(BSDI4)
  401.   setpassent(1);
  402. #endif
  403.   return cpw;
  404. }
  405. #endif /* USESHADOW */
  406. static char *_get_ppw_info(pool *p, const char *u)
  407. {
  408.   struct passwd *pw;
  409.   char *cpw = NULL;
  410.   pw = p_getpwnam(u);
  411.   if(pw)
  412.     cpw = pstrdup(p,pw->pw_passwd);
  413.   return cpw;
  414. }
  415. /* high-level auth handlers
  416.  */
  417. /* cmd->argv[0] : user name
  418.  * cmd->argv[1] : cleartext password
  419.  */
  420. MODRET pw_auth(cmd_rec *cmd)
  421. {
  422.   time_t now;
  423.   char *cpw;
  424.   time_t lstchg = -1,max = -1,inact = -1,disable = -11;
  425.   const char *name;
  426.   name = cmd->argv[0];
  427.   time(&now);
  428.   if(persistent_passwd)
  429.     cpw = _get_ppw_info(cmd->tmp_pool,name);
  430.   else
  431.     cpw = _get_pw_info(cmd->tmp_pool,name,&lstchg,NULL,&max,NULL,&inact,&disable);
  432.   if(!cpw)
  433.     return ERROR_INT(cmd,AUTH_NOPWD);
  434.   if(auth_check(cmd->tmp_pool,cpw,cmd->argv[0],cmd->argv[1]))
  435.     return ERROR_INT(cmd,AUTH_BADPWD);
  436.   if(lstchg > (time_t)0 && max > (time_t)0 &&
  437.      inact > (time_t)0)
  438.     if(now > lstchg + max + inact)
  439.       return ERROR_INT(cmd,AUTH_AGEPWD);
  440.   if(disable > (time_t)0 && now > disable)
  441.     return ERROR_INT(cmd,AUTH_DISABLEDPWD);
  442.   return HANDLED(cmd);
  443. }
  444. /*
  445.  * cmd->argv[0] = hashed password,
  446.  * cmd->argv[1] = user,
  447.  * cmd->argv[2] = cleartext
  448.  */
  449. MODRET pw_check(cmd_rec *cmd)
  450. {
  451.   static char *pw,*cpw;
  452.   cpw = cmd->argv[0];
  453.   pw = cmd->argv[2];
  454.   if(strcmp(crypt(pw,cpw),cpw) != 0)
  455.     return ERROR(cmd);
  456.   return HANDLED(cmd);
  457. }
  458. MODRET pw_uid_name(cmd_rec *cmd)
  459. {
  460.   idmap_t *m;
  461.   struct passwd *pw;
  462.   uid_t uid;
  463.   uid = (uid_t)cmd->argv[0];
  464.   m = _auth_lookup_id(uid_table,uid);
  465.   if(!m->name) {
  466.     /* wasn't cached, so perform a lookup */
  467.     if(PERSISTENT_PASSWD)
  468.       pw = p_getpwuid(uid);
  469.     else
  470.       pw = getpwuid(uid);
  471.     if(pw)
  472.       m->name = pstrdup(permanent_pool,pw->pw_name);
  473.     else {
  474.       char buf[10];
  475.       snprintf(buf, sizeof(buf), "%lu",(ULONG)uid);
  476.       m->name = pstrdup(permanent_pool,buf);
  477.     }
  478.   }
  479.   return mod_create_data(cmd,m->name);
  480. }
  481. MODRET pw_gid_name(cmd_rec *cmd)
  482. {
  483.   idmap_t *m;
  484.   struct group *gr;
  485.   gid_t gid;
  486.   gid = (gid_t)cmd->argv[0];
  487.   m = _auth_lookup_id(gid_table,gid);
  488.   if(!m->name) {
  489.     if(PERSISTENT_GROUP)
  490.       gr = p_getgrgid(gid);
  491.     else
  492.       gr = getgrgid(gid);
  493.     if(gr)
  494.       m->name = pstrdup(permanent_pool,gr->gr_name);
  495.     else {
  496.       char buf[10];
  497.       snprintf(buf, sizeof(buf), "%lu",(ULONG)gid);
  498.       m->name = pstrdup(permanent_pool,buf);
  499.     }
  500.   }
  501.   return mod_create_data(cmd,m->name);
  502. }
  503. MODRET pw_name_uid(cmd_rec *cmd)
  504. {
  505.   struct passwd *pw;
  506.   const char *name;
  507.   name = cmd->argv[0];
  508.   
  509.   if(PERSISTENT_PASSWD)
  510.     pw = p_getpwnam(name);
  511.   else
  512.     pw = getpwnam(name);
  513.   if(pw)
  514.     return mod_create_data(cmd,(void*)pw->pw_uid);
  515.   return ERROR(cmd);
  516. }
  517. MODRET pw_name_gid(cmd_rec *cmd)
  518. {
  519.   struct group *gr;
  520.   const char *name;
  521.   name = cmd->argv[0];
  522.   
  523.   if(PERSISTENT_GROUP)
  524.     gr = p_getgrnam(name);
  525.   else
  526.     gr = getgrnam(name);
  527.   if(gr)
  528.     return mod_create_data(cmd,(void*)gr->gr_gid);
  529.   return ERROR(cmd);
  530. }
  531. MODRET set_persistentpasswd(cmd_rec *cmd)
  532. {
  533.   int b;
  534.   CHECK_ARGS(cmd,1);
  535.   CHECK_CONF(cmd,CONF_ROOT);
  536.   b = get_boolean(cmd,1);
  537.   if(b != -1)
  538.     persistent = b;
  539.   return HANDLED(cmd);
  540. }
  541. MODRET set_authuserfile(cmd_rec *cmd)
  542. {
  543.   CHECK_ARGS(cmd,1);
  544.   CHECK_CONF(cmd,CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);
  545.   add_config_param_str("AuthUserFile",1,cmd->argv[1]);
  546.   return HANDLED(cmd);
  547. }
  548. MODRET set_authgroupfile(cmd_rec *cmd)
  549. {
  550.   CHECK_ARGS(cmd,1);
  551.   CHECK_CONF(cmd,CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);
  552.   add_config_param_str("AuthGroupFile",1,cmd->argv[1]);
  553.   return HANDLED(cmd);
  554. }
  555. static int unixpw_init()
  556. {
  557.   memset(uid_table,0,sizeof(uid_table));
  558.   memset(gid_table,0,sizeof(gid_table));
  559. #ifdef HAVE__PW_STAYOPEN
  560.   _pw_stayopen = 1;
  561. #endif
  562.   return 0;
  563. }
  564. static int unixpw_child()
  565. {
  566.   const char *file;
  567.   file = (const char*)get_param_ptr(main_server->conf,"AuthUserFile",FALSE);
  568.   if(file) {
  569.     endpwent(); 
  570.     persistent_passwd = 1; /* Force persistent mode */
  571.     pwdfname = file;
  572.     p_endpwent();
  573.     p_setpwent();
  574.   }
  575.   file = (const char*)get_param_ptr(main_server->conf,"AuthGroupFile",FALSE);
  576.   if(file) {
  577.     endgrent();
  578.     persistent_group = 1;
  579.     grpfname = file;
  580.     p_endgrent();
  581.     p_setgrent();
  582.   }
  583.   
  584.   return 0;
  585. }
  586. static conftable unixpw_config[] = {
  587.   { "PersistentPasswd", set_persistentpasswd, NULL },
  588.   { "AuthUserFile", set_authuserfile, NULL },
  589.   { "AuthGroupFile", set_authgroupfile, NULL },
  590.   { NULL, NULL, NULL }
  591. };
  592. static authtable unixpw_auth[] = {
  593.   { 0,  "setpwent", pw_setpwent },
  594.   { 0,  "endpwent", pw_endpwent },
  595.   { 0,  "setgrent",     pw_setgrent },
  596.   { 0,  "endgrent", pw_endgrent },
  597.   { 0, "getpwent", pw_getpwent },
  598.   { 0,  "getgrent", pw_getgrent },
  599.   { 0,  "getpwnam", pw_getpwnam },
  600.   { 0, "getpwuid", pw_getpwuid },
  601.   { 0,  "getgrnam",     pw_getgrnam     },
  602.   { 0,  "getgrgid",     pw_getgrgid     },
  603.   { 0,  "auth",         pw_auth },
  604.   { 0,  "check", pw_check },
  605.   { 0,  "uid_name", pw_uid_name },
  606.   { 0,  "gid_name", pw_gid_name },
  607.   { 0,  "name_uid", pw_name_uid },
  608.   { 0,  "name_gid", pw_name_gid },
  609.   { 0,  NULL }
  610. };
  611. module unixpw_module = {
  612.   NULL,NULL, /* Always NULL */
  613.   0x20, /* API Version 2.0 */
  614.   "unixpw",
  615.   unixpw_config, /* Configuration directive table */
  616.   NULL, /* No command handlers */
  617.   unixpw_auth, /* Authentication handlers */
  618.   unixpw_init,unixpw_child /* Initialization functions */
  619. };