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

网络编程

开发平台:

Unix_Linux

  1. /*
  2.  * APOP authentication, derived from MH 6.8.3
  3.  */
  4. /*
  5.  * Copyright (c) 1997 by Qualcomm Incorporated.
  6.  */
  7. #ifdef HAVE_CONFIG_H
  8. #include <config.h>
  9. #endif
  10. #ifdef APOP
  11. #include <sys/types.h>
  12. #include <sys/stat.h>
  13. #include <stdio.h>
  14. #ifdef GDBM
  15. # include <gdbm.h>
  16. #else
  17. # include <ndbm.h>
  18. #endif
  19. #include <fcntl.h>
  20. #include <pwd.h>
  21. #if HAVE_STRINGS_H
  22. # include <strings.h>
  23. #endif
  24. #if HAVE_SYS_FILE_H
  25. # include <sys/file.h>
  26. #endif
  27. #include <popper.h>
  28. #include <md5.h>
  29. #include <string.h>
  30. #include <flock.h>
  31. /*
  32.  * Obscure password so a cleartext search doesn't come up with
  33.  * something interesting.
  34.  *
  35.  */
  36. char *
  37. obscure(string)
  38. char *string;
  39. {
  40.     unsigned char *cp, *newstr;
  41.     cp = newstr = (unsigned char *)strdup(string);
  42.     while (*cp)
  43.        *cp++ ^= 0xff;
  44.     return((char *)newstr);
  45. }
  46. int 
  47. pop_apop (p)
  48. POP *p;
  49. {
  50.     register char *cp;
  51.     char    buffer[BUFSIZ];
  52.     register unsigned char *dp;
  53.     unsigned char *ep,
  54.    digest[16];
  55.     struct passwd *pw;
  56. #ifdef GDBM
  57. char apop_file[BUFSIZ];
  58. #else
  59.     char apop_dir[BUFSIZ];
  60. #endif
  61.     struct stat st;
  62.     datum   key,
  63.     ddatum;
  64. #ifdef GDBM
  65. GDBM_FILE db;
  66. #else
  67.     DBM    *db;
  68. #endif
  69.     MD5_CTX mdContext;
  70.     int f;
  71.     (void)strncpy(p->user, p->pop_parm[1], sizeof(p->user));
  72.     p->user[sizeof(p->user)-1] = 0;
  73.     pop_log(p, LOG_INFO, "apop "%s"", p->user);
  74. #ifdef AUTHFILE
  75.     if (checkauthfile(p->user) != 0)
  76.         return (pop_msg(p,POP_FAILURE,"Permission denied for %s.",p->user));
  77. #endif
  78. #ifdef NONAUTHFILE
  79.     if (checknonauthfile(p->user) != 0)
  80.         return (pop_msg(p,POP_FAILURE,"Permission denied for %s.",p->user));
  81. #endif
  82.     if (((pw = getpwnam (p->user)) == NULL) || (pw->pw_passwd == NULL) ||
  83.  (*pw->pw_passwd == '')) {
  84. return (pop_auth_fail(p,POP_FAILURE, pwerrmsg ,p->user));
  85.     }
  86.     if(pw->pw_uid == 0)
  87.     return (pop_auth_fail(p,POP_FAILURE,
  88.     "User %s login denied.", p->user));
  89. #ifdef GDBM
  90.     if ((db = gdbm_open (APOP, 512, GDBM_READER, 0, 0)) == NULL)
  91. #else
  92.     if ((db = dbm_open (APOP, O_RDONLY, 0)) == NULL)
  93. #endif
  94. return (pop_auth_fail(p,POP_FAILURE, 
  95. "POP authorization DB not available (%s)",
  96. p->user, strerror(errno)));
  97. #ifdef GDBM
  98.     (void) strncpy(apop_file, APOP, sizeof(apop_file) - 1);
  99. apop_file[sizeof(apop_file)-1] = '';
  100.     if (stat (apop_file, &st) != -1
  101.     && (st.st_mode & 0777) != 0600) {
  102. gdbm_close (db);
  103. return(pop_auth_fail(p, POP_FAILURE, 
  104. "POP authorization DB has wrong mode (0%o)",
  105. st.st_mode & 0777));
  106.     }
  107.     f = open(apop_file, O_RDONLY);
  108.     if(f == -1) {
  109. int e = errno;
  110. gdbm_close (db);
  111. return(pop_auth_fail(p, POP_FAILURE, 
  112. "unable to lock POP authorization DB (%s)",
  113. strerror(e)));
  114.     }
  115. #else  
  116.     (void) strncpy(apop_dir, APOP, sizeof(apop_dir) - 5);
  117. #if defined(BSD44_DBM)
  118.     (void) strcat(apop_dir, ".db");
  119. #else
  120.     (void) strcat(apop_dir, ".dir");
  121. #endif
  122.     if (stat (apop_dir, &st) != -1
  123.     && (st.st_mode & 0777) != 0600) {
  124. dbm_close (db);
  125. return(pop_auth_fail(p, POP_FAILURE, 
  126. "POP authorization DB has wrong mode (0%o)",
  127. st.st_mode & 0777));
  128.     }
  129.     f = open(apop_dir, O_RDONLY);
  130.     if(f == -1) {
  131. int e = errno;
  132. dbm_close (db);
  133. return(pop_auth_fail(p, POP_FAILURE, 
  134. "unable to lock POP authorization DB (%s)",
  135. strerror(e)));
  136.     }
  137. #endif 
  138.     if (flock (f, LOCK_SH) == -1) {
  139. int e = errno;
  140. (void) close(f);
  141. #ifdef GDBM
  142. gdbm_close (db);
  143. #else
  144. dbm_close (db);
  145. #endif
  146. return(pop_auth_fail(p, POP_FAILURE, 
  147. "unable to lock POP authorization DB (%s)",
  148. strerror(e)));
  149.     }
  150.     key.dsize = strlen (key.dptr = p->user) + 1;
  151. #ifdef GDBM
  152.     ddatum = gdbm_fetch (db, key);
  153. #else
  154.     ddatum = dbm_fetch (db, key);
  155. #endif
  156.     if (ddatum.dptr == NULL) {
  157. (void) close(f);
  158. #ifdef GDBM
  159. gdbm_close (db);
  160. #else
  161. dbm_close (db);
  162. #endif
  163. return(pop_auth_fail(p, POP_FAILURE, "not authorized"));
  164.     }
  165. #ifdef GDBM
  166. gdbm_close (db);
  167. #else
  168.     dbm_close (db);
  169. #endif
  170.     (void) close(f);
  171.     MD5Init(&mdContext);
  172.     MD5Update(&mdContext, (unsigned char *)p->md5str, strlen(p->md5str));
  173.     MD5Update(&mdContext, (unsigned char *)obscure(ddatum.dptr), (ddatum.dsize - 1));
  174.     MD5Final(digest, &mdContext);
  175.     cp = buffer;
  176.     for (ep = (dp = digest) + sizeof digest / sizeof digest[0];
  177.      dp < ep;
  178.      cp += 2)
  179. (void) sprintf (cp, "%02x", *dp++ & 0xff);
  180.     *cp = '';
  181.     if (strcmp(p->pop_parm[2], buffer)) {
  182. return(pop_auth_fail(p, POP_FAILURE, "authentication failure"));
  183.     }
  184. #ifdef DEBUG
  185.     if (p->debug)
  186. pop_log(p, LOG_NOTICE, "APOP authentication ok for "%s"", p->user);
  187. #endif
  188.     if (genpath(p) < 0)
  189. return(pop_msg(p, POP_FAILURE, "Unable to create temporary drop name"));
  190.     /*  Make a temporary copy of the user's maildrop */
  191.     /*    and set the group and user id */
  192.     if (pop_dropcopy(p, pw) != POP_SUCCESS) return (POP_FAILURE);
  193.     /*  Initialize the last-message-accessed number */
  194.     p->last_msg = 0;
  195.     /*  Authorization completed successfully */
  196.     return (pop_msg (p,POP_SUCCESS, "%s has %d message(s) (%d octets).",
  197.             p->user, p->msg_count, p->drop_size));
  198. }
  199. #endif /* APOP */