pop_pass.c
上传用户:dayuan858
上传日期:2007-01-04
资源大小:194k
文件大小:16k
源码类别:

网络编程

开发平台:

Unix_Linux

  1. /*
  2.  * Copyright (c) 1989 Regents of the University of California.
  3.  * All rights reserved.  The Berkeley software License Agreement
  4.  * specifies the terms and conditions for redistribution.
  5.  */
  6. /*
  7.  * Copyright (c) 1997 by Qualcomm Incorporated.
  8.  */
  9. #include <config.h>
  10. #include <stdio.h>
  11. #include <sys/types.h>
  12. #include <string.h>
  13. #if HAVE_STRINGS_H
  14. # include <strings.h>
  15. #endif
  16. #include <pwd.h>
  17. #include "popper.h"
  18. #define SLEEP_SECONDS 10
  19. /* This error message is vague on purpose to help reduce help improve
  20.    security at the inconvience of administrators and users */
  21. char *pwerrmsg = "Password supplied for "%s" is incorrect.";
  22. #ifdef NONAUTHFILE
  23. checknonauthfile(user) 
  24.      char *user;
  25. {
  26.     char buf[MAXUSERNAMELEN+1];
  27.     FILE *fp;
  28.     char cool = 0;
  29.     if ((fp = fopen(NONAUTHFILE, "r")) != NULL) {
  30. while (fgets(buf, MAXUSERNAMELEN+1, fp)) {
  31.     buf[strlen(buf) -1] = '';
  32.     if (!strcmp(buf, user)) {
  33. fclose(fp);
  34. return(-1);
  35.     }
  36. }
  37. fclose(fp);
  38.     }
  39.     return(0);
  40. }
  41. #endif
  42. #ifdef AUTHFILE
  43. checkauthfile(user) 
  44.      char *user;
  45. {
  46.     char buf[MAXUSERNAMELEN+1];
  47.     FILE *fp;
  48.     char cool = 0;
  49.     if ((fp = fopen(AUTHFILE, "r")) != NULL) {
  50. while (fgets(buf, MAXUSERNAMELEN+1, fp)) {
  51.     buf[strlen(buf) -1] = '';
  52.     if (!strcmp(buf, user)) {
  53. fclose(fp);
  54. return(0);
  55.     }
  56. }
  57. fclose(fp);
  58.     }
  59.     return(-1);
  60. }
  61. #endif
  62. int auth_user_kerberos (p, pw)
  63. POP     *   p;
  64. struct passwd *pw;
  65. {
  66. #ifdef KERBEROS
  67.     char lrealm[REALM_SZ];
  68.     int status;
  69.     struct passwd *pwp;
  70.  
  71.     if ((status = krb_get_lrealm(lrealm,1)) == KFAILURE) {
  72.         pop_log(p, LOG_WARNING, "%s: (%s.%s@%s) %s", p->client, kdata.pname, 
  73. kdata.pinst, kdata.prealm, krb_err_txt[status]);
  74.         return(pop_msg(p,POP_FAILURE,
  75.             "Kerberos error:  "%s".", krb_err_txt[status]));
  76.     }
  77. # ifdef KUSEROK
  78.     if (kuserok(&kdata, p->user)) {
  79.         pop_log(p, LOG_WARNING, "%s: (%s.%s@%s): not in %s's ACL.",
  80.     p->client, kdata.pname, kdata.pinst, kdata.prealm, p->user);
  81. return(pop_msg(p,POP_FAILURE, "Not in %s's ACL.", p->user));
  82.     }
  83. # else
  84.     if (strcmp(kdata.prealm,lrealm))  {
  85.          pop_log(p, LOG_WARNING, "%s: (%s.%s@%s) realm not accepted.", 
  86.  p->client, kdata.pname, kdata.pinst, kdata.prealm);
  87.  return(pop_msg(p,POP_FAILURE,
  88.      "Kerberos realm "%s" not accepted.", kdata.prealm));
  89.     }
  90.     if (strcmp(kdata.pinst,"")) {
  91.         pop_log(p, LOG_WARNING, "%s: (%s.%s@%s) instance not accepted.", 
  92.  p->client, kdata.pname, kdata.pinst, kdata.prealm);
  93.         return(pop_msg(p,POP_FAILURE,
  94.       "Must use null Kerberos(tm) instance -  "%s.%s" not accepted.",
  95.       kdata.pname, kdata.pinst));
  96.     }
  97. # endif /* KUSEROK */
  98.     return(POP_SUCCESS);
  99. #else /* Kerberos not defined */
  100.     return(pop_log(p, LOG_WARNING,
  101. "Kerberos failure: The popper has not been compiled with -DKERBEROS"));
  102. #endif /* KERBEROS */
  103. }
  104. #ifdef AUTH_SPECIAL
  105.     char *crypt();
  106. #if defined(SUNOS4) && !defined(ISC)
  107. #include <sys/label.h>
  108. #include <sys/audit.h>
  109. #include <pwdadj.h>
  110. static int
  111. auth_user(p, pw)
  112. POP     *   p;
  113. struct passwd *pw;
  114. {
  115.     struct passwd_adjunct *pwadj;
  116.     /*  Look for the user in the shadow password file */
  117.     if ((pwadj = getpwanam(p->user)) == NULL) {
  118. sleep(SLEEP_SECONDS);
  119. return (pop_msg(p,POP_FAILURE,
  120. "(shadow) Password supplied for "%s" is empty.",p->user));
  121.     } else {
  122.         pw->pw_passwd = (char *)strdup(pwadj->pwa_passwd);
  123.     }
  124.     /*  We don't accept connections from users with null passwords */
  125.     /*  Compare the supplied password with the password file entry */
  126.     if ((pw->pw_passwd == NULL) || (*pw->pw_passwd == '') ||
  127. strcmp(crypt(p->pop_parm[1], pw->pw_passwd), pw->pw_passwd)) {
  128. sleep(SLEEP_SECONDS);
  129. return (pop_msg(p,POP_FAILURE,pwerrmsg, p->user));
  130.     }
  131.     return(POP_SUCCESS);
  132. }
  133. #endif /* SUNOS4 */
  134. #if defined(SOLARIS2) || defined(AUX) || defined(UXPDS)
  135. #include <shadow.h>
  136. static int
  137. auth_user(p, pw)
  138. POP     *   p;
  139. struct passwd *pw;
  140. {
  141.     register struct spwd * pwd;
  142.     long today;
  143.     /*  Look for the user in the shadow password file */
  144.     if ((pwd = getspnam(p->user)) == NULL) {
  145.         if (!strcmp(pw->pw_passwd, "x")) { /* This my be a YP entry */
  146.     sleep(SLEEP_SECONDS);
  147.     return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
  148. }
  149.     } else {
  150. today = (long)time((time_t *)NULL)/24/60/60;
  151. /* Check for expiration date */
  152. if (pwd->sp_expire > 0 && today > pwd->sp_expire) {
  153.     sleep(SLEEP_SECONDS);
  154.     return (pop_msg(p,POP_FAILURE,""%s": account expired.",p->user));
  155. }
  156. /* Check if password is valid */
  157. if (pwd->sp_max > 0 && today > pwd->sp_lstchg+pwd->sp_max) {
  158.     sleep(SLEEP_SECONDS);
  159.     return (pop_msg(p,POP_FAILURE,""%s": account expired.",p->user));
  160. }
  161. pw->pw_passwd = (char *)strdup(pwd->sp_pwdp);
  162. endspent();
  163.     }
  164.     /*  We don't accept connections from users with null passwords */
  165.     /*  Compare the supplied password with the password file entry */
  166.     if ((pw->pw_passwd == NULL) || (*pw->pw_passwd == '') ||
  167. strcmp(crypt(p->pop_parm[1], pw->pw_passwd), pw->pw_passwd)) {
  168. sleep(SLEEP_SECONDS);
  169. return (pop_msg(p, POP_FAILURE, pwerrmsg, p->user));
  170.     }
  171.     return(POP_SUCCESS);
  172. }
  173. #endif /* SOLARIS2 || AUX */
  174. #if defined(PTX) || defined(ISC)
  175. #include <shadow.h>
  176. static int
  177. auth_user(p, pw)
  178. POP     *   p;
  179. struct passwd *pw;
  180. {
  181.     register struct spwd * pwd;
  182.     long today;
  183.     /*  Look for the user in the shadow password file */
  184.     if ((pwd = getspnam(p->user)) == NULL) {
  185.         if (!strcmp(pw->pw_passwd, "x")) { /* This my be a YP entry */
  186.     sleep(SLEEP_SECONDS);
  187.     return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
  188. }
  189.     } else {
  190. pw->pw_passwd = (char *)strdup(pwd->sp_pwdp);
  191.     }
  192.     /*  We don't accept connections from users with null passwords */
  193.     /*  Compare the supplied password with the password file entry */
  194.     if ((pw->pw_passwd == NULL) || (*pw->pw_passwd == '') ||
  195. strcmp(crypt(p->pop_parm[1], pw->pw_passwd), pw->pw_passwd)) {
  196. sleep(SLEEP_SECONDS);
  197. return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
  198.     }
  199.     return(POP_SUCCESS);
  200. }
  201. #endif /* PTX */
  202. #if defined(POPSCO) || defined(HPUX10)
  203. #ifdef POPSCO
  204. # include <sys/security.h>
  205. # include <sys/audit.h>
  206. #else
  207. # include <hpsecurity.h>
  208. #endif
  209. #include <prot.h>
  210. #define PASSWD(p) p->ufld.fd_encrypt
  211. static int
  212. auth_user(p, pw)
  213. POP     *   p;
  214. struct passwd *pw;
  215. {
  216.     register struct pr_passwd *pr;
  217.     if ((pr = getprpwnam(p->user)) == NULL) {
  218.         if (!strcmp(pw->pw_passwd, "x")) {
  219.     sleep(SLEEP_SECONDS);
  220.     return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
  221. }
  222. /*  We don't accept connections from users with null passwords */
  223. if ((pw->pw_passwd == NULL) || (*pw->pw_passwd == '') ||
  224.              (strcmp(bigcrypt(p->pop_parm[1], pw->pw_passwd), pw->pw_passwd) &&
  225.       strcmp(crypt (p->pop_parm[1], pw->pw_passwd), pw->pw_passwd))) {
  226.     sleep(SLEEP_SECONDS);
  227.     return(pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
  228. }
  229.     } else {
  230. /*  We don't accept connections from users with null passwords */
  231. /*  Compare the supplied password with the password file entry */
  232. if ((PASSWD(pr) == NULL) || (*PASSWD(pr) == '')) {
  233.     sleep(SLEEP_SECONDS);
  234.     return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
  235. }
  236. if (strcmp(bigcrypt(p->pop_parm[1], PASSWD(pr)), PASSWD(pr)) &&
  237.     strcmp(crypt(p->pop_parm[1], PASSWD(pr)), PASSWD(pr))) {
  238.     sleep(SLEEP_SECONDS);
  239.     return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
  240. }
  241.     }
  242.     return(POP_SUCCESS);
  243. }
  244. #endif /* POPSCO || HPUX10 */
  245. #ifdef ULTRIX
  246. #include <auth.h>
  247. static int
  248. auth_user(p, pw)
  249. struct passwd  *   pw;
  250. POP     *   p;
  251. {
  252.     AUTHORIZATION *auth, *getauthuid();
  253.     if ((auth = getauthuid(pw->pw_uid)) == NULL) {
  254.         if (!strcmp(pw->pw_passwd, "x")) { /* This my be a YP entry */
  255.     sleep(SLEEP_SECONDS);
  256.     return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
  257. }
  258.     } else {
  259. pw->pw_passwd = (char *)strdup(auth->a_password);
  260.     }
  261.     /*  We don't accept connections from users with null passwords */
  262.     /*  Compare the supplied password with the password file entry */
  263.     if ((pw->pw_passwd == NULL) || (*pw->pw_passwd == '')) {
  264. sleep(SLEEP_SECONDS);
  265. return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
  266.     }
  267.     if (strcmp(crypt16(p->pop_parm[1], pw->pw_passwd), pw->pw_passwd) &&
  268. strcmp(crypt(p->pop_parm[1], pw->pw_passwd), pw->pw_passwd)) {
  269. sleep(SLEEP_SECONDS);
  270. return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
  271.     }
  272.     return(POP_SUCCESS);
  273. }
  274. #endif /* ULTRIX */
  275. #ifdef OSF1
  276. #include <sys/types.h>
  277. #include <sys/security.h>
  278. #include <prot.h>
  279. #define   PASSWD(p)   (p->ufld.fd_encrypt)
  280. static int
  281. auth_user(p, pw)
  282. POP     *   p;
  283. struct passwd *pw;
  284. {
  285.     register struct pr_passwd *pr;
  286.     if ((pr = getprpwnam(p->user)) == NULL) {
  287.         if (!strcmp(pw->pw_passwd, "x")) { /* This my be a YP entry */
  288.     sleep(SLEEP_SECONDS);
  289.     return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
  290. }
  291.     } else {
  292. pw->pw_passwd = (char *)strdup(PASSWD(pr));
  293.     }
  294.     /*  We don't accept connections from users with null passwords */
  295.     /*  Compare the supplied password with the password file entry */
  296.     if ((pw->pw_passwd == NULL) || (*pw->pw_passwd == '')) {
  297. sleep(SLEEP_SECONDS);
  298. return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
  299.     }
  300.     if (strcmp(bigcrypt(p->pop_parm[1], pw->pw_passwd), pw->pw_passwd) &&
  301. strcmp(crypt(p->pop_parm[1], pw->pw_passwd), pw->pw_passwd)) {
  302. sleep(SLEEP_SECONDS);
  303. return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
  304.     }
  305.     return(POP_SUCCESS);
  306. }
  307. #endif        /* OSF1 */
  308. #ifdef UNIXWARE
  309. #include <shadow.h>
  310. static int
  311. auth_user(p, pw)
  312. struct passwd  *   pw;
  313. POP     *   p;
  314. {
  315.     register struct spwd * pwd;
  316.     long today;
  317.     /*  Look for the user in the shadow password file */
  318.     if ((pwd = getspnam(p->user)) == NULL) {
  319.         if (!strcmp(pw->pw_passwd, "x")) { /* This my be a YP entry */
  320.     sleep(SLEEP_SECONDS);
  321.     return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
  322. }
  323.     } else {
  324. today = (long)time((time_t *)NULL)/24/60/60;
  325. /* Check for expiration date */
  326. if (pwd->sp_expire > 0 && today > pwd->sp_expire) {
  327.     sleep(SLEEP_SECONDS);
  328.     return (pop_msg(p,POP_FAILURE,""%s": account expired.",p->user));
  329. }
  330. /* Check if password is valid */
  331. if (pwd->sp_max > 0 && today > pwd->sp_lstchg+pwd->sp_max) {
  332.     sleep(SLEEP_SECONDS);
  333.     return (pop_msg(p,POP_FAILURE,""%s": account expired.",p->user));
  334. }
  335. pw->pw_passwd = (char *)strdup(pwd->sp_pwdp);
  336. endspent();
  337.     }
  338.     /*  We don't accept connections from users with null passwords */
  339.     /*  Compare the supplied password with the password file entry */
  340.     if ((pw->pw_passwd == NULL) || (*pw->pw_passwd == '') ||
  341. strcmp(crypt(p->pop_parm[1], pw->pw_passwd), pw->pw_passwd)) {
  342. sleep(SLEEP_SECONDS);
  343. return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
  344.     }
  345.     return(POP_SUCCESS);
  346. }
  347. #endif /* UNIXWARE */
  348. #ifdef LINUX
  349. #ifdef HAVE_SHADOW_H
  350. #include <shadow.h>
  351. #endif
  352.  
  353. static int
  354. auth_user(p, pw)
  355. POP     *   p;
  356. struct passwd *pw;
  357. {
  358.     register struct spwd * pwd;
  359.     long today;
  360.     /*  Look for the user in the shadow password file */
  361.     if ((pwd = getspnam(p->user)) == NULL) {
  362.         if (!strcmp(pw->pw_passwd, "x")) { /* This my be a YP entry */
  363.     sleep(SLEEP_SECONDS);
  364.     return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
  365. }
  366.     } else {
  367. today = (long)time((time_t *)NULL)/24/60/60;
  368. /* Check for expiration date */
  369. if (pwd->sp_expire > 0 && today > pwd->sp_expire) {
  370.     sleep(SLEEP_SECONDS);
  371.     return (pop_msg(p,POP_FAILURE,""%s": account expired.",p->user));
  372. }
  373. /* Check if password is valid */
  374. if (pwd->sp_max > 0 && today > pwd->sp_lstchg+pwd->sp_max) {
  375.     sleep(SLEEP_SECONDS);
  376.     return (pop_msg(p,POP_FAILURE,""%s": account expired.",p->user));
  377. }
  378. pw->pw_passwd = (char *)strdup(pwd->sp_pwdp);
  379. endspent();
  380.     }
  381.     /*  We don't accept connections from users with null passwords */
  382.     /*  Compare the supplied password with the password file entry */
  383.     /*  pw_encrypt() ??                                            */
  384.     if ((pw->pw_passwd == NULL) || (*pw->pw_passwd == '') || 
  385.     (strcmp(crypt(p->pop_parm[1], pw->pw_passwd), pw->pw_passwd)
  386. #ifdef HAVE_PW_ENCRYPT
  387.      && strcmp(pw_encrypt(p->pop_parm[1], pw->pw_passwd), pw->pw_passwd)
  388. #endif
  389.      )){
  390. sleep(SLEEP_SECONDS);
  391. return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
  392.     }
  393.     return(POP_SUCCESS);
  394. }
  395. #endif  /* LINUX */
  396. #else /* NOT AUTH_SPECIAL */
  397. char *crypt();
  398. static int
  399. auth_user(p, pw)
  400. POP     *   p;
  401. struct passwd  *   pw;
  402. {
  403.     /*  We don't accept connections from users with null passwords */
  404.     /*  Compare the supplied password with the password file entry */
  405.     if ((pw->pw_passwd == NULL) || (*pw->pw_passwd == '') ||
  406. strcmp(crypt(p->pop_parm[1], pw->pw_passwd), pw->pw_passwd)) {
  407. sleep(SLEEP_SECONDS);
  408. return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
  409.     }
  410.     return(POP_SUCCESS);
  411. }
  412. #endif /* AUTH_SPECIAL */
  413. /* 
  414.  *  pass:   Obtain the user password from a POP client
  415.  */
  416. #ifdef SECURENISPLUS
  417. # include <rpc/rpc.h>
  418. # include <rpc/key_prot.h>
  419. #endif
  420. int pop_pass (p)
  421. POP     *   p;
  422. {
  423.     struct passwd pw, *pwp;
  424. #ifdef CHECK_SHELL
  425.     char *getusershell();
  426.     void endusershell();
  427.     char *shell;
  428.     char *cp;
  429.     int shellvalid;
  430. #endif
  431. #ifdef SECURENISPLUS
  432.     UID_T uid_save;
  433.     char net_name[MAXNETNAMELEN],
  434.  secretkey[HEXKEYBYTES + 1];
  435.     *secretkey = '';
  436. #endif
  437. #ifdef NONAUTHFILE
  438.     /* Is the user not authorized to use POP? */
  439.     if (checknonauthfile(p->user) != 0) {
  440. sleep(SLEEP_SECONDS);
  441. return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
  442.     }
  443. #endif
  444. #ifdef AUTHFILE
  445.     /* Is the user authorized to use POP? */
  446.     if (checkauthfile(p->user) != 0) {
  447. sleep(SLEEP_SECONDS);
  448. return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
  449.     }
  450. #endif
  451.     /*  Look for the user in the password file */
  452.     if ((pwp = getpwnam(p->user)) == NULL) {
  453. sleep(SLEEP_SECONDS);
  454. return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
  455.     }
  456.     pw = *pwp;
  457. #ifdef SECURENISPLUS
  458.     /*  we must do this keyserv stuff (as well as auth_user()!) as the user */
  459.     uid_save = geteuid();
  460.     seteuid(pw.pw_uid);
  461.     /*  see if DES keys are already known to the keyserv(1m) */
  462.     if (! key_secretkey_is_set()) {
  463. /*  keys are not known, so we must get the DES keys
  464.     and register with the keyserv(1m) */
  465. getnetname(net_name);
  466. if (getpublickey(net_name, secretkey)) {
  467.     if (strlen(p->pop_parm[1]) > 8) (p->pop_parm[1])[8] = '';
  468.     if (! getsecretkey(net_name, secretkey, p->pop_parm[1]) ||
  469. *secretkey == '') {
  470. sleep(SLEEP_SECONDS);
  471. return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
  472.     }
  473.     key_setsecret(secretkey);
  474.     memset(secretkey, '', sizeof(secretkey));
  475. } else {
  476.     /* if there are no keys defined, we assume that password entry
  477.        either resides in /etc/shadow or "root" has access to the
  478.        corresponding NIS+ entry */
  479.     seteuid(0);
  480. }
  481.     }
  482. #endif
  483. #ifdef BLOCK_UID
  484.     if (pw.pw_uid <= BLOCK_UID)
  485. return (pop_msg(p,POP_FAILURE,
  486.     "Access is blocked for UIDs below %d", BLOCK_UID));
  487. #endif
  488. #ifdef CHECK_SHELL
  489.     /*  Disallow anyone who does not have a standard shell as returned by
  490.      *  getusershell(), unless the sys admin has included the wildcard
  491.      *  shell in /etc/shells.  (default wildcard - /POPPER/ANY/SHELL)
  492.      */
  493.     if ((shell = pw.pw_shell) == NULL || *shell == 0)
  494. /* You can default the shell, but I don't think it's a good idea */
  495. /* shell = "/usr/bin/sh"; */
  496. return(pop_msg(p, POP_FAILURE, "No user shell defined"));
  497.     
  498.     for (shellvalid = 0; !shellvalid && ((cp = getusershell()) != NULL);)
  499. if (!strcmp(cp, WILDCARD_SHELL) || !strcmp(cp, shell))
  500.      shellvalid = 1;
  501.     endusershell();
  502.     if (!shellvalid)
  503. return(pop_msg(p, POP_FAILURE, ""%s": shell not found.", p->user));
  504. #endif
  505.     if ((p->kerberos ? auth_user_kerberos(p, pw) : auth_user(p, pwp))
  506. != POP_SUCCESS) {
  507.     pop_log(p,POP_PRIORITY,"Failed attempted login to %s from host %s",
  508.     p->user, p->client);
  509. return(POP_FAILURE);
  510.     }
  511. #ifdef SECURENISPLUS
  512.     seteuid(uid_save);
  513. #endif
  514.     /*  Make a temporary copy of the user's maildrop */
  515.     /*    and set the group and user id */
  516.     /*    and get information about the maildrop */
  517.     if (pop_dropcopy(p, &pw) != POP_SUCCESS) return (POP_FAILURE);
  518.     /*  Initialize the last-message-accessed number */
  519.     p->last_msg = 0;
  520.     /*  Authorization completed successfully */
  521.     return (pop_msg (p,POP_SUCCESS,
  522.         "%s has %d message%s (%d octets).",
  523.             p->user,p->msg_count, p->msg_count == 1 ? "" : "s", p->drop_size));
  524. }