home *** CD-ROM | disk | FTP | other *** search
/ Big Green CD 8 / BGCD_8_Dev.iso / NEXTSTEP / UNIX / Mail / qpopper-2.4-MIHS / pop_init.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-09-12  |  9.6 KB  |  384 lines

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