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

网络编程

开发平台:

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 <errno.h>
  11. #include <stdio.h>
  12. #include <sys/types.h>
  13. #if HAVE_SYS_NETINET_IN_H
  14. # include <sys/netinet/in.h>
  15. #endif
  16. #if HAVE_NETINET_IN_H
  17. # include <netinet/in.h>
  18. #endif
  19. #include <netdb.h>
  20. #include <arpa/inet.h>
  21. #include <string.h>
  22. #if HAVE_SYS_PARAM_H
  23. # include <sys/param.h>
  24. #endif
  25. #if HAVE_STRINGS_H
  26. # include <strings.h>
  27. #endif
  28. #ifndef HAVE_INDEX
  29. # define index(s,c) strchr(s,c)
  30. # define rindex(s,c) strrchr(s,c)
  31. #endif
  32. #ifndef HAVE_BCOPY
  33. # define bcopy(src,dest,len)   (void) (memcpy(dest, src, len))
  34. # define bzero(dest,len)       (void) (memset(dest, (char)NULL, len))
  35. # define bcmp(b1,b2,n)         memcmp(b1,b2,n)
  36. #endif
  37. #include <popper.h>
  38. /* CNS Kerberos IV */
  39. #ifdef KERBEROS
  40. AUTH_DAT kdata;
  41. #endif
  42. extern int      errno;
  43. /*
  44. #ifdef POPSCO
  45. extern struct state _res;
  46. #endif
  47. */
  48. #ifndef HAVE_STRDUP
  49. #include <stddef.h>
  50. #include <stdlib.h>
  51. char *
  52. strdup(str)
  53.         char *str;
  54. {
  55.     int len;
  56.     char *copy;
  57.     len = strlen(str) + 1;
  58.     if (!(copy = malloc((u_int)len)))
  59. return((char *)NULL);
  60.     bcopy(str, copy, len);
  61.     return(copy);
  62. }
  63. #endif
  64. authenticate(p, addr)
  65.      POP     *p;
  66.      struct sockaddr_in *addr;
  67. {
  68. #ifdef KERBEROS
  69.     Key_schedule schedule;
  70.     KTEXT_ST ticket;
  71.     char instance[INST_SZ];  
  72.     char version[9];
  73.     int auth;
  74.   
  75.     if (p->kerberos) {
  76. strcpy(instance, "*");
  77. auth = krb_recvauth(0L, 0, &ticket, KERBEROS_SERVICE, instance,
  78.     addr, (struct sockaddr_in *) NULL,
  79.     &kdata, "", schedule, version);
  80. if (auth != KSUCCESS) {
  81.     pop_msg(p, POP_FAILURE, "Kerberos authentication failure: %s", 
  82.     krb_err_txt[auth]);
  83.     pop_log(p, LOG_WARNING, "%s: (%s.%s@%s) %s", p->client, 
  84.     kdata.pname, kdata.pinst, kdata.prealm, krb_err_txt[auth]);
  85.     return(POP_FAILURE);
  86. }
  87. # ifdef DEBUG
  88. if (p->debug)
  89.     pop_log(p, POP_DEBUG, "%s.%s@%s (%s): ok", kdata.pname, 
  90. kdata.pinst, kdata.prealm, inet_ntoa(addr->sin_addr));
  91. # endif /* DEBUG */
  92. strncpy(p->user, kdata.pname, sizeof(p->user));
  93.     }
  94. #endif /* KERBEROS */
  95.     return(POP_SUCCESS);
  96. }
  97. /* 
  98.  *  init:   Start a Post Office Protocol session
  99.  */
  100. pop_init(p, argcount, argmessage)
  101. POP     *       p;
  102. int             argcount;
  103. char    **      argmessage;
  104. {
  105.     struct sockaddr_in      cs;                 /*  Communication parameters */
  106.     struct hostent      *   ch;                 /*  Client host information */
  107.     int                     errflag = 0;
  108.     int                     c;
  109.     int                     len;
  110.     extern char         *   optarg;
  111.     int                     options = 0;
  112.     int                     sp = 0;             /*  Socket pointer */
  113.     char                *   trace_file_name;
  114.     struct hostent *   hp = NULL;
  115.     /*  Initialize the POP parameter block */
  116.     bzero ((char *)p,(int)sizeof(POP));
  117.     /*  Initialize maildrop status variables in the POP parameter block */
  118.     p->msgs_deleted = 0;
  119.     p->last_msg = 0;
  120.     p->bytes_deleted = 0;
  121.     p->drop_size = 0;
  122.     p->mmdf_separator = NULL;
  123.     p->bulldir = BULLDIR;
  124.     p->dirty = 0;
  125.     p->xmitting = 0;
  126.     p->kerberos = 0;
  127. #ifdef SERVER_MODE
  128.     p->server_mode = 1;
  129. #else
  130.     p->server_mode = 0;
  131. #endif
  132.     /*  Save my name in a global variable */
  133.     p->myname = argmessage[0];
  134.     /*  Get the name of our host */
  135.     if ((p->myhost = (char *)malloc(MAXHOSTNAMELEN+1)) == NULL) {
  136. perror("malloc");
  137. exit(1);
  138.     }
  139.     (void)gethostname(p->myhost,MAXHOSTNAMELEN);
  140.     if (hp = gethostbyname(p->myhost)) {
  141. if (! index(hp->h_name, '.')) { /* FQN not returned */
  142.     /*
  143.      * SVR4 resolver is stupid and returns h_name as whatever
  144.      * you gave gethostbyname.  Thus do a reverse lookup
  145.      * on the first address and hope for the best.
  146.      */
  147.     u_long x = *(u_long *)hp->h_addr_list[0];
  148.     if ((hp = gethostbyaddr((char *)&x, 4, AF_INET)) != NULL) {
  149.         (void) strncpy (p->myhost, hp->h_name, MAXHOSTNAMELEN);
  150.         p->myhost[MAXHOSTNAMELEN] = '';
  151.     }
  152. }
  153. else {
  154.     (void) strncpy (p->myhost, hp->h_name, MAXHOSTNAMELEN);
  155.     p->myhost[MAXHOSTNAMELEN] = '';
  156. }
  157.     }
  158.     /*  Open the log file */
  159. #ifdef SYSLOG42
  160.     (void)openlog(p->myname,0);
  161. #else
  162.     (void)openlog(p->myname,POP_LOGOPTS,POP_FACILITY);
  163. #endif
  164.     /*  Process command line arguments */
  165.     while ((c = getopt(argcount,argmessage,"dkst:T:b:")) != EOF)
  166.         switch (c) {
  167.             /*  Debugging requested */
  168.             case 'd':
  169.                 p->debug++;
  170.                 options |= SO_DEBUG;
  171. #ifdef DEBUG
  172. if (p->debug)
  173.     pop_log(p,POP_PRIORITY,"Debugging turned on");
  174. #endif
  175.                 break;
  176. #ifdef KERBEROS
  177.     case 'k':
  178. p->kerberos++;
  179.     break;
  180. #endif /* KERBEROS */
  181.             /* Stats requested */
  182.             case 's':
  183.                 p->stats++;
  184.                 break;
  185.     /* Bulletins requested */
  186.             case 'b':
  187.                 p->bulldir = optarg;
  188.                 break;
  189.             /*  Debugging trace file specified */
  190.             case 't':
  191.                 p->debug++;
  192. #ifdef DEBUG
  193. if (p->trace)
  194.     pop_log(p,POP_PRIORITY,
  195.     "Tracing session and debugging information in file "%s"",
  196.     trace_file_name);
  197. #endif
  198.                 if ((p->trace = fopen(optarg,"a+")) == NULL) {
  199.                     pop_log(p,POP_PRIORITY,
  200.                         "Unable to open trace file "%s", err = %d",
  201.                             optarg,errno);
  202.                     exit(1);
  203. }
  204.                 trace_file_name = optarg;
  205.                 break;
  206.     /*  Timeout value passed.  Default changed */
  207.     case 'T':
  208. pop_timeout = atoi(optarg);
  209. break;
  210.             /*  Unknown option received */
  211.             default:
  212.                 errflag++;
  213.         }
  214.     /*  Exit if bad options specified */
  215.     if (errflag) {
  216. #ifdef KERBEROS
  217.         (void)fprintf(stderr,"Usage: %s [-d] [-k] [-s] [-t trace-file] [-T timeout] [-b bulldir]n",argmessage[0]);
  218. #else
  219.         (void)fprintf(stderr,"Usage: %s [-d] [-s] [-t trace-file] [-T timeout] [-b bulldir]n",argmessage[0]);
  220. #endif
  221.         exit(1);
  222.     }
  223.     /*  Get the address and socket of the client to whom I am speaking */
  224.     len = sizeof(cs);
  225.     if (getpeername(sp,(struct sockaddr *)&cs,&len) < 0){
  226.         pop_log(p,POP_PRIORITY,
  227.             "Unable to obtain socket and address of client, err = %d",errno);
  228.         exit(1);
  229.     }
  230.     /*  Save the dotted decimal form of the client's IP address 
  231.         in the POP parameter block */
  232.     p->ipaddr = (char *)strdup(inet_ntoa(cs.sin_addr));
  233.     /*  Save the client's port */
  234.     p->ipport = ntohs(cs.sin_port);
  235.     /*  Get the canonical name of the host to whom I am speaking */
  236.     ch = gethostbyaddr((char *) &cs.sin_addr, sizeof(cs.sin_addr), AF_INET);
  237.     if (ch == NULL){
  238.         pop_log(p,POP_PRIORITY,
  239.             "(v%s) Unable to get canonical name of client, err = %d",
  240.     VERSION, errno);
  241.         p->client = p->ipaddr;
  242.     }
  243.     /*  Save the cannonical name of the client host in 
  244.         the POP parameter block */
  245.     else {
  246. #ifndef BIND43
  247.         p->client = (char *)strdup(ch->h_name);
  248. #else
  249. # ifndef SCOR5
  250. #       include <arpa/nameser.h>
  251. #       include <resolv.h>
  252. # endif
  253.         /*  Distrust distant nameservers */
  254. #if !(defined(BSD) && (BSD >= 199103)) && !defined(OSF1) && !defined(HPUX10)
  255. # if (!defined(__RES)) || (__RES < 19940415)
  256. #  ifdef SCOR5
  257. extern struct __res_state _res;
  258. #  else
  259.         extern struct state     _res;
  260. #  endif
  261. # endif
  262. #endif
  263.         struct hostent      *   ch_again;
  264.         char            *   *   addrp;
  265. char h_name[MAXHOSTNAMELEN + 1];
  266.         /*  We already have a fully-qualified name */
  267. #ifdef RES_DEFNAMES
  268.         _res.options &= ~RES_DEFNAMES;
  269. #endif
  270. strncpy(h_name, ch->h_name, sizeof(h_name));
  271.         /*  See if the name obtained for the client's IP 
  272.             address returns an address */
  273.         if ((ch_again = gethostbyname(h_name)) == NULL) {
  274.             pop_log(p,POP_PRIORITY,
  275.                 "Client at "%s" resolves to an unknown host name "%s"",
  276.                     p->ipaddr, h_name);
  277.             p->client = p->ipaddr;
  278.         }
  279.         else {
  280.             /*  Save the host name (the previous value was 
  281.                 destroyed by gethostbyname) */
  282.             p->client = (char *)strdup(ch_again->h_name);
  283.             /*  Look for the client's IP address in the list returned 
  284.                 for its name */
  285.             for (addrp=ch_again->h_addr_list; *addrp; ++addrp)
  286.                 if (bcmp(*addrp,&(cs.sin_addr),sizeof(cs.sin_addr)) == 0) break;
  287.             if (!*addrp) {
  288.                 pop_log (p,POP_PRIORITY,
  289.                     "Client address "%s" not listed for its host name "%s"",
  290.                         p->ipaddr,h_name);
  291.                 p->client = p->ipaddr;
  292.             }
  293.         }
  294. #ifdef RES_DEFNAMES
  295. /* 
  296.  *  Must restore nameserver options since code in crypt uses
  297.  *  gethostbyname call without fully qualified domain name!
  298.  */
  299. _res.options |= RES_DEFNAMES;
  300. #endif
  301. #endif /* BIND43 */
  302.     }
  303.     /*  Create input file stream for TCP/IP communication */
  304.     if ((p->input = fdopen(sp,"r")) == NULL){
  305.         pop_log(p,POP_PRIORITY,
  306.             "Unable to open communication stream for input, err = %d",errno);
  307.         exit (1);
  308.     }
  309.     /*  Create output file stream for TCP/IP communication */
  310.     if ((p->output = fdopen(sp,"w")) == NULL){
  311.         pop_log(p,POP_PRIORITY,
  312.             "Unable to open communication stream for output, err = %d",errno);
  313.         exit (1);
  314.     }
  315. #ifdef DEBUG
  316.     if (p->debug)
  317. pop_log(p,POP_PRIORITY,
  318.     "(v%s) Servicing request from "%s" at %s",
  319. VERSION,p->client,p->ipaddr);
  320. #endif
  321.     return(authenticate(p, &cs));
  322. }