home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / kerberosIV / kerberos / kerberos.c next >
Encoding:
C/C++ Source or Header  |  1991-02-25  |  20.6 KB  |  815 lines

  1. /*
  2.  * $Source: /usr/src/kerberosIV/kerberos/RCS/kerberos.c,v $
  3.  * $Author: bostic $
  4.  *
  5.  * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute
  6.  * of Technology.
  7.  *
  8.  * For copying and distribution information, please see the file
  9.  * <mit-copyright.h>.
  10.  */
  11.  
  12. #ifndef lint
  13. static char *rcsid_kerberos_c =
  14. "$Header: /usr/src/kerberosIV/kerberos/RCS/kerberos.c,v 4.21 91/02/25 15:40:32 bostic Exp Locker: bostic $";
  15. #endif  lint
  16.  
  17. #include <mit-copyright.h>
  18. #include <stdio.h>
  19. #include <sys/types.h>
  20. #include <sys/socket.h>
  21. #include <netinet/in.h>
  22. #include <netdb.h>
  23. #include <signal.h>
  24. #include <sgtty.h>
  25. #include <sys/ioctl.h>
  26. #include <sys/time.h>
  27. #include <sys/file.h>
  28. #include <ctype.h>
  29.  
  30. #include <des.h>
  31. #include <krb.h>
  32. #include <klog.h>
  33. #include <prot.h>
  34. #include <krb_db.h>
  35. #include <kdc.h>
  36.  
  37. extern int errno;
  38.  
  39. struct sockaddr_in sin = {AF_INET};
  40. int     f;
  41.  
  42. /* XXX several files in libkdb know about this */
  43. char *progname;
  44.  
  45. static Key_schedule master_key_schedule;
  46. static C_Block master_key;
  47.  
  48. static struct timeval kerb_time;
  49. static Principal a_name_data;    /* for requesting user */
  50. static Principal s_name_data;    /* for services requested */
  51. static C_Block session_key;
  52. static C_Block user_key;
  53. static C_Block service_key;
  54. static u_char master_key_version;
  55. static char k_instance[INST_SZ];
  56. static char log_text[128];
  57. static char *lt;
  58. static int more;
  59.  
  60. static int mflag;        /* Are we invoked manually? */
  61. static int lflag;        /* Have we set an alterate log file? */
  62. static char *log_file;        /* name of alt. log file */
  63. static int nflag;        /* don't check max age */
  64. static int rflag;        /* alternate realm specified */
  65.  
  66. /* fields within the received request packet */
  67. static u_char req_msg_type;
  68. static u_char req_version;
  69. static char *req_name_ptr;
  70. static char *req_inst_ptr;
  71. static char *req_realm_ptr;
  72. static u_char req_no_req;
  73. static u_long req_time_ws;
  74.  
  75. int req_act_vno = KRB_PROT_VERSION; /* Temporary for version skew */
  76.  
  77. static char local_realm[REALM_SZ];
  78.  
  79. /* statistics */
  80. static long q_bytes;        /* current bytes remaining in queue */
  81. static long q_n;        /* how many consecutive non-zero
  82.                  * q_bytes   */
  83. static long max_q_bytes;
  84. static long max_q_n;
  85. static long n_auth_req;
  86. static long n_appl_req;
  87. static long n_packets;
  88. static long n_user;
  89. static long n_server;
  90.  
  91. extern char *sys_errlist[];
  92. static long max_age = -1;
  93. static long pause_int = -1;
  94.  
  95. static void check_db_age();
  96. static void hang();
  97.  
  98. /*
  99.  * Print usage message and exit.
  100.  */
  101. static void usage()
  102. {
  103.     fprintf(stderr, "Usage: %s [-s] [-m] [-n] [-p pause_seconds]%s%s\n", progname, 
  104.         " [-a max_age] [-l log_file] [-r realm]"
  105.         ," [database_pathname]"
  106.         );
  107.     exit(1);
  108. }
  109.  
  110.  
  111. main(argc, argv)
  112.     int     argc;
  113.     char  **argv;
  114. {
  115.     struct sockaddr_in from;
  116.     register int n;
  117.     int     on = 1;
  118.     int     child;
  119.     struct servent *sp;
  120.     int     fromlen;
  121.     static KTEXT_ST pkt_st;
  122.     KTEXT   pkt = &pkt_st;
  123.     Principal *p;
  124.     int     more, kerror;
  125.     C_Block key;
  126.     int c;
  127.     extern char *optarg;
  128.     extern int optind;
  129.  
  130.     progname = argv[0];
  131.  
  132.     while ((c = getopt(argc, argv, "snmp:a:l:r:")) != EOF) {
  133.     switch(c) {
  134.     case 's':
  135.         /*
  136.          * Set parameters to slave server defaults.
  137.          */
  138.         if (max_age == -1 && !nflag)
  139.         max_age = ONE_DAY;    /* 24 hours */
  140.         if (pause_int == -1)
  141.         pause_int = FIVE_MINUTES; /* 5 minutes */
  142.         if (lflag == 0) {
  143.         log_file = KRBSLAVELOG;
  144.         lflag++;
  145.         }
  146.         break;
  147.     case 'n':
  148.         max_age = -1;    /* don't check max age. */
  149.         nflag++;
  150.         break;
  151.     case 'm':
  152.         mflag++;        /* running manually; prompt for master key */
  153.         break;
  154.     case 'p':
  155.         /* Set pause interval. */
  156.         if (!isdigit(optarg[0]))
  157.         usage();
  158.         pause_int = atoi(optarg);
  159.         if ((pause_int < 5) ||  (pause_int > ONE_HOUR)) {
  160.         fprintf(stderr, "pause_int must be between 5 and 3600 seconds.\n");
  161.         usage();
  162.         }
  163.         break;
  164.     case 'a':
  165.         /* Set max age. */
  166.         if (!isdigit(optarg[0])) 
  167.         usage();
  168.         max_age = atoi(optarg);
  169.         if ((max_age < ONE_HOUR) || (max_age > THREE_DAYS)) {
  170.         fprintf(stderr, "max_age must be between one hour and three days, in seconds\n");
  171.         usage();
  172.         }
  173.         break;
  174.     case 'l':
  175.         /* Set alternate log file */
  176.         lflag++;
  177.         log_file = optarg;
  178.         break;
  179.     case 'r':
  180.         /* Set realm name */
  181.         rflag++;
  182.         strcpy(local_realm, optarg);
  183.         break;
  184.     default:
  185.         usage();
  186.         break;
  187.     }
  188.     }
  189.  
  190.     if (optind == (argc-1)) {
  191.     if (kerb_db_set_name(argv[optind]) != 0) {
  192.         fprintf(stderr, "Could not set alternate database name\n");
  193.         exit(1);
  194.     }
  195.     optind++;
  196.     }
  197.  
  198.     if (optind != argc)
  199.     usage();
  200.     
  201.     printf("Kerberos server starting\n");
  202.     
  203.     if ((!nflag) && (max_age != -1))
  204.     printf("\tMaximum database age: %d seconds\n", max_age);
  205.     if (pause_int != -1)
  206.     printf("\tSleep for %d seconds on error\n", pause_int);
  207.     else
  208.     printf("\tSleep forever on error\n");
  209.     if (mflag)
  210.     printf("\tMaster key will be entered manually\n");
  211.     
  212.     printf("\tLog file is %s\n", lflag ? log_file : KRBLOG);
  213.  
  214.     if (lflag)
  215.     kset_logfile(log_file);
  216.     
  217.     /* find our hostname, and use it as the instance */
  218.     if (gethostname(k_instance, INST_SZ)) {
  219.     fprintf(stderr, "%s: gethostname error\n", progname);
  220.     exit(1);
  221.     }
  222.  
  223.     if ((sp = getservbyname("kerberos", "udp")) == 0) {
  224.     fprintf(stderr, "%s: udp/kerberos unknown service\n", progname);
  225.     exit(1);
  226.     }
  227.     sin.sin_port = sp->s_port;
  228.  
  229.     if ((f = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
  230.     fprintf(stderr, "%s: Can't open socket\n", progname);
  231.     exit(1);
  232.     }
  233.     if (setsockopt(f, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
  234.     fprintf(stderr, "%s: setsockopt (SO_REUSEADDR)\n", progname);
  235.  
  236.     if (bind(f, (struct sockaddr *)&sin, S_AD_SZ) < 0) {
  237.     fprintf(stderr, "%s: Can't bind socket\n", progname);
  238.     exit(1);
  239.     }
  240.     /* do all the database and cache inits */
  241.     if (n = kerb_init()) {
  242.     if (mflag) {
  243.         printf("Kerberos db and cache init ");
  244.         printf("failed = %d ...exiting\n", n);
  245.         exit(-1);
  246.     } else {
  247.         klog(L_KRB_PERR,
  248.         "Kerberos db and cache init failed = %d ...exiting", n);
  249.         hang();
  250.     }
  251.     }
  252.  
  253.     /* Make sure database isn't stale */
  254.     check_db_age();
  255.     
  256.     /* setup master key */
  257.     if (kdb_get_master_key (mflag, master_key, master_key_schedule) != 0) {
  258.       klog (L_KRB_PERR, "kerberos: couldn't get master key.\n");
  259.       exit (-1);
  260.     }
  261.     kerror = kdb_verify_master_key (master_key, master_key_schedule, stdout);
  262.     if (kerror < 0) {
  263.       klog (L_KRB_PERR, "Can't verify master key.");
  264.       bzero (master_key, sizeof (master_key));
  265.       bzero (master_key_schedule, sizeof (master_key_schedule));
  266.       exit (-1);
  267.     }
  268.  
  269.     master_key_version = (u_char) kerror;
  270.  
  271.     fprintf(stdout, "\nCurrent Kerberos master key version is %d\n",
  272.         master_key_version);
  273.  
  274.     if (!rflag) {
  275.     /* Look up our local realm */
  276.     krb_get_lrealm(local_realm, 1);
  277.     }
  278.     fprintf(stdout, "Local realm: %s\n", local_realm);
  279.     fflush(stdout);
  280.  
  281.     if (set_tgtkey(local_realm)) {
  282.     /* Ticket granting service unknown */
  283.     klog(L_KRB_PERR, "Ticket granting ticket service unknown");
  284.     fprintf(stderr, "Ticket granting ticket service unknown\n");
  285.     exit(1);
  286.     }
  287.     if (mflag) {
  288.     if ((child = fork()) != 0) {
  289.         printf("Kerberos started, PID=%d\n", child);
  290.         exit(0);
  291.     }
  292.     setup_disc();
  293.     }
  294.     /* receive loop */
  295.     for (;;) {
  296.     fromlen = S_AD_SZ;
  297.     n = recvfrom(f, pkt->dat, MAX_PKT_LEN, 0,
  298.         (struct sockaddr *)&from, &fromlen);
  299.     if (n > 0) {
  300.         pkt->length = n;
  301.         pkt->mbz = 0; /* force zeros to catch runaway strings */
  302.         /* see what is left in the input queue */
  303.         ioctl(f, FIONREAD, &q_bytes);
  304.         gettimeofday(&kerb_time, NULL);
  305.         q_n++;
  306.         max_q_n = max(max_q_n, q_n);
  307.         n_packets++;
  308.         klog(L_NET_INFO,
  309.      "q_byt %d, q_n %d, rd_byt %d, mx_q_b %d, mx_q_n %d, n_pkt %d",
  310.          q_bytes, q_n, n, max_q_bytes, max_q_n, n_packets, 0);
  311.         max_q_bytes = max(max_q_bytes, q_bytes);
  312.         if (!q_bytes)
  313.         q_n = 0;    /* reset consecutive packets */
  314.         kerberos(&from, pkt);
  315.     } else
  316.         klog(L_NET_ERR,
  317.         "%s: bad recvfrom n = %d errno = %d", progname, n, errno, 0);
  318.     }
  319. }
  320.  
  321.  
  322. kerberos(client, pkt)
  323.     struct sockaddr_in *client;
  324.     KTEXT   pkt;
  325. {
  326.     static KTEXT_ST rpkt_st;
  327.     KTEXT   rpkt = &rpkt_st;
  328.     static KTEXT_ST ciph_st;
  329.     KTEXT   ciph = &ciph_st;
  330.     static KTEXT_ST tk_st;
  331.     KTEXT   tk = &tk_st;
  332.     static KTEXT_ST auth_st;
  333.     KTEXT   auth = &auth_st;
  334.     AUTH_DAT ad_st;
  335.     AUTH_DAT *ad = &ad_st;
  336.  
  337.  
  338.     static struct in_addr client_host;
  339.     static int msg_byte_order;
  340.     static int swap_bytes;
  341.     static u_char k_flags;
  342.     char   *p_name, *instance;
  343.     u_long  lifetime;
  344.     int     i;
  345.     C_Block key;
  346.     Key_schedule key_s;
  347.     char   *ptr;
  348.  
  349.  
  350.  
  351.     ciph->length = 0;
  352.  
  353.     client_host = client->sin_addr;
  354.  
  355.     /* eval macros and correct the byte order and alignment as needed */
  356.     req_version = pkt_version(pkt);    /* 1 byte, version */
  357.     req_msg_type = pkt_msg_type(pkt);    /* 1 byte, Kerberos msg type */
  358.  
  359.     req_act_vno = req_version;
  360.  
  361.     /* check packet version */
  362.     if (req_version != KRB_PROT_VERSION) {
  363.     lt = klog(L_KRB_PERR,
  364.     "KRB prot version mismatch: KRB =%d request = %d",
  365.           KRB_PROT_VERSION, req_version, 0);
  366.     /* send an error reply */
  367.     kerb_err_reply(client, pkt, KERB_ERR_PKT_VER, lt);
  368.     return;
  369.     }
  370.     msg_byte_order = req_msg_type & 1;
  371.  
  372.     swap_bytes = 0;
  373.     if (msg_byte_order != HOST_BYTE_ORDER) {
  374.     swap_bytes++;
  375.     }
  376.     klog(L_KRB_PINFO,
  377.     "Prot version: %d, Byte order: %d, Message type: %d",
  378.      req_version, msg_byte_order, req_msg_type);
  379.  
  380.     switch (req_msg_type & ~1) {
  381.  
  382.     case AUTH_MSG_KDC_REQUEST:
  383.     {
  384.         u_long  time_ws;    /* Workstation time */
  385.         u_long  req_life;    /* Requested liftime */
  386.         char   *service;    /* Service name */
  387.         char   *instance;    /* Service instance */
  388.         int     kerno;    /* Kerberos error number */
  389.         n_auth_req++;
  390.         tk->length = 0;
  391.         k_flags = 0;    /* various kerberos flags */
  392.  
  393.  
  394.         /* set up and correct for byte order and alignment */
  395.         req_name_ptr = (char *) pkt_a_name(pkt);
  396.         req_inst_ptr = (char *) pkt_a_inst(pkt);
  397.         req_realm_ptr = (char *) pkt_a_realm(pkt);
  398.         bcopy(pkt_time_ws(pkt), &req_time_ws, sizeof(req_time_ws));
  399.         /* time has to be diddled */
  400.         if (swap_bytes) {
  401.         swap_u_long(req_time_ws);
  402.         }
  403.         ptr = (char *) pkt_time_ws(pkt) + 4;
  404.  
  405.         req_life = (u_long) (*ptr++);
  406.  
  407.         service = ptr;
  408.         instance = ptr + strlen(service) + 1;
  409.  
  410.         rpkt = &rpkt_st;
  411.         klog(L_INI_REQ,
  412.         "Initial ticket request Host: %s User: \"%s\" \"%s\"",
  413.            inet_ntoa(client_host), req_name_ptr, req_inst_ptr, 0);
  414.  
  415.         if (i = check_princ(req_name_ptr, req_inst_ptr, 0,
  416.         &a_name_data)) {
  417.         kerb_err_reply(client, pkt, i, lt);
  418.         return;
  419.         }
  420.         tk->length = 0;    /* init */
  421.         if (strcmp(service, "krbtgt"))
  422.         klog(L_NTGT_INTK,
  423.             "INITIAL request from %s.%s for %s.%s",
  424.              req_name_ptr, req_inst_ptr, service, instance, 0);
  425.         /* this does all the checking */
  426.         if (i = check_princ(service, instance, lifetime,
  427.         &s_name_data)) {
  428.         kerb_err_reply(client, pkt, i, lt);
  429.         return;
  430.         }
  431.         /* Bound requested lifetime with service and user */
  432.         lifetime = min(req_life, ((u_long) s_name_data.max_life));
  433.         lifetime = min(lifetime, ((u_long) a_name_data.max_life));
  434. #ifdef NOENCRYPTION
  435.         bzero(session_key, sizeof(C_Block));
  436. #else
  437.         /* random session key */
  438.         random_key(session_key);
  439. #endif
  440.  
  441.         /* unseal server's key from master key */
  442.         bcopy(&s_name_data.key_low, key, 4);
  443.         bcopy(&s_name_data.key_high, ((long *) key) + 1, 4);
  444.         kdb_encrypt_key(key, key, master_key,
  445.                 master_key_schedule, DECRYPT);
  446.         /* construct and seal the ticket */
  447.         krb_create_ticket(tk, k_flags, a_name_data.name,
  448.         a_name_data.instance, local_realm,
  449.          client_host.s_addr, session_key, lifetime, kerb_time.tv_sec,
  450.              s_name_data.name, s_name_data.instance, key);
  451.         bzero(key, sizeof(key));
  452.         bzero(key_s, sizeof(key_s));
  453.  
  454.         /*
  455.          * get the user's key, unseal it from the server's key, and
  456.          * use it to seal the cipher 
  457.          */
  458.  
  459.         /* a_name_data.key_low a_name_data.key_high */
  460.         bcopy(&a_name_data.key_low, key, 4);
  461.         bcopy(&a_name_data.key_high, ((long *) key) + 1, 4);
  462.  
  463.         /* unseal the a_name key from the master key */
  464.         kdb_encrypt_key(key, key, master_key, 
  465.                 master_key_schedule, DECRYPT);
  466.  
  467.         create_ciph(ciph, session_key, s_name_data.name,
  468.             s_name_data.instance, local_realm, lifetime,
  469.           s_name_data.key_version, tk, kerb_time.tv_sec, key);
  470.  
  471.         /* clear session key */
  472.         bzero(session_key, sizeof(session_key));
  473.  
  474.         bzero(key, sizeof(key));
  475.  
  476.  
  477.  
  478.         /* always send a reply packet */
  479.         rpkt = create_auth_reply(req_name_ptr, req_inst_ptr,
  480.         req_realm_ptr, req_time_ws, 0, a_name_data.exp_date,
  481.         a_name_data.key_version, ciph);
  482.         sendto(f, rpkt->dat, rpkt->length, 0,
  483.         (struct sockaddr *)client, S_AD_SZ);
  484.         bzero(&a_name_data, sizeof(a_name_data));
  485.         bzero(&s_name_data, sizeof(s_name_data));
  486.         break;
  487.     }
  488.     case AUTH_MSG_APPL_REQUEST:
  489.     {
  490.         u_long  time_ws;    /* Workstation time */
  491.         u_long  req_life;    /* Requested liftime */
  492.         char   *service;    /* Service name */
  493.         char   *instance;    /* Service instance */
  494.         int     kerno;    /* Kerberos error number */
  495.         char    tktrlm[REALM_SZ];
  496.  
  497.         n_appl_req++;
  498.         tk->length = 0;
  499.         k_flags = 0;    /* various kerberos flags */
  500.  
  501.         auth->length = 4 + strlen(pkt->dat + 3);
  502.         auth->length += (int) *(pkt->dat + auth->length) +
  503.         (int) *(pkt->dat + auth->length + 1) + 2;
  504.  
  505.         bcopy(pkt->dat, auth->dat, auth->length);
  506.  
  507.         strncpy(tktrlm, auth->dat + 3, REALM_SZ);
  508.         if (set_tgtkey(tktrlm)) {
  509.         lt = klog(L_ERR_UNK,
  510.             "FAILED realm %s unknown. Host: %s ",
  511.               tktrlm, inet_ntoa(client_host));
  512.         kerb_err_reply(client, pkt, kerno, lt);
  513.         return;
  514.         }
  515.         kerno = krb_rd_req(auth, "ktbtgt", tktrlm, client_host.s_addr,
  516.         ad, 0);
  517.  
  518.         if (kerno) {
  519.         klog(L_ERR_UNK, "FAILED krb_rd_req from %s: %s",
  520.              inet_ntoa(client_host), krb_err_txt[kerno]);
  521.         kerb_err_reply(client, pkt, kerno, "krb_rd_req failed");
  522.         return;
  523.         }
  524.         ptr = (char *) pkt->dat + auth->length;
  525.  
  526.         bcopy(ptr, &time_ws, 4);
  527.         ptr += 4;
  528.  
  529.         req_life = (u_long) (*ptr++);
  530.  
  531.         service = ptr;
  532.         instance = ptr + strlen(service) + 1;
  533.  
  534.         klog(L_APPL_REQ, "APPL Request %s.%s@%s on %s for %s.%s",
  535.          ad->pname, ad->pinst, ad->prealm, inet_ntoa(client_host),
  536.          service, instance, 0);
  537.  
  538.         if (strcmp(ad->prealm, tktrlm)) {
  539.         kerb_err_reply(client, pkt, KERB_ERR_PRINCIPAL_UNKNOWN,
  540.              "Can't hop realms");
  541.         return;
  542.         }
  543.         if (!strcmp(service, "changepw")) {
  544.         kerb_err_reply(client, pkt, KERB_ERR_PRINCIPAL_UNKNOWN,
  545.              "Can't authorize password changed based on TGT");
  546.         return;
  547.         }
  548.         kerno = check_princ(service, instance, req_life,
  549.         &s_name_data);
  550.         if (kerno) {
  551.         kerb_err_reply(client, pkt, kerno, lt);
  552.         return;
  553.         }
  554.         /* Bound requested lifetime with service and user */
  555.         lifetime = min(req_life,
  556.           (ad->life - ((kerb_time.tv_sec - ad->time_sec) / 300)));
  557.         lifetime = min(lifetime, ((u_long) s_name_data.max_life));
  558.  
  559.         /* unseal server's key from master key */
  560.         bcopy(&s_name_data.key_low, key, 4);
  561.         bcopy(&s_name_data.key_high, ((long *) key) + 1, 4);
  562.         kdb_encrypt_key(key, key, master_key,
  563.                 master_key_schedule, DECRYPT);
  564.         /* construct and seal the ticket */
  565.  
  566. #ifdef NOENCRYPTION
  567.         bzero(session_key, sizeof(C_Block));
  568. #else
  569.         /* random session key */
  570.         random_key(session_key);
  571. #endif
  572.  
  573.         krb_create_ticket(tk, k_flags, ad->pname, ad->pinst,
  574.                   ad->prealm, client_host.s_addr,
  575.                   session_key, lifetime, kerb_time.tv_sec,
  576.                   s_name_data.name, s_name_data.instance,
  577.                   key);
  578.         bzero(key, sizeof(key));
  579.         bzero(key_s, sizeof(key_s));
  580.  
  581.         create_ciph(ciph, session_key, service, instance,
  582.             local_realm,
  583.             lifetime, s_name_data.key_version, tk,
  584.             kerb_time.tv_sec, ad->session);
  585.  
  586.         /* clear session key */
  587.         bzero(session_key, sizeof(session_key));
  588.  
  589.         bzero(ad->session, sizeof(ad->session));
  590.  
  591.         rpkt = create_auth_reply(ad->pname, ad->pinst,
  592.                      ad->prealm, time_ws,
  593.                      0, 0, 0, ciph);
  594.         sendto(f, rpkt->dat, rpkt->length, 0,
  595.         (struct sockaddr *)client, S_AD_SZ);
  596.         bzero(&s_name_data, sizeof(s_name_data));
  597.         break;
  598.     }
  599.  
  600.  
  601. #ifdef notdef_DIE
  602.     case AUTH_MSG_DIE:
  603.     {
  604.         lt = klog(L_DEATH_REQ,
  605.             "Host: %s User: \"%s\" \"%s\" Kerberos killed",
  606.             inet_ntoa(client_host), req_name_ptr, req_inst_ptr, 0);
  607.         exit(0);
  608.     }
  609. #endif notdef_DIE
  610.  
  611.     default:
  612.     {
  613.         lt = klog(L_KRB_PERR,
  614.         "Unknown message type: %d from %s port %u",
  615.         req_msg_type, inet_ntoa(client_host),
  616.         ntohs(client->sin_port));
  617.         break;
  618.     }
  619.     }
  620. }
  621.  
  622.  
  623. /*
  624.  * setup_disc 
  625.  *
  626.  * disconnect all descriptors, remove ourself from the process
  627.  * group that spawned us. 
  628.  */
  629.  
  630. setup_disc()
  631. {
  632.  
  633.     int     s;
  634.  
  635.     for (s = 0; s < 3; s++) {
  636.     (void) close(s);
  637.     }
  638.  
  639.     (void) open("/dev/null", 0);
  640.     (void) dup2(0, 1);
  641.     (void) dup2(0, 2);
  642.  
  643.     s = open("/dev/tty", 2);
  644.  
  645.     if (s >= 0) {
  646.     ioctl(s, TIOCNOTTY, (struct sgttyb *) 0);
  647.     (void) close(s);
  648.     }
  649.     (void) chdir("/tmp");
  650.     return;
  651. }
  652.  
  653.  
  654. /*
  655.  * kerb_er_reply creates an error reply packet and sends it to the
  656.  * client. 
  657.  */
  658.  
  659. kerb_err_reply(client, pkt, err, string)
  660.     struct sockaddr_in *client;
  661.     KTEXT   pkt;
  662.     long    err;
  663.     char   *string;
  664.  
  665. {
  666.     static KTEXT_ST e_pkt_st;
  667.     KTEXT   e_pkt = &e_pkt_st;
  668.     static char e_msg[128];
  669.  
  670.     strcpy(e_msg, "\nKerberos error -- ");
  671.     strcat(e_msg, string);
  672.     cr_err_reply(e_pkt, req_name_ptr, req_inst_ptr, req_realm_ptr,
  673.          req_time_ws, err, e_msg);
  674.     sendto(f, e_pkt->dat, e_pkt->length, 0, (struct sockaddr *)client, S_AD_SZ);
  675.  
  676. }
  677.  
  678. /*
  679.  * Make sure that database isn't stale.
  680.  *
  681.  * Exit if it is; we don't want to tell lies.
  682.  */
  683.  
  684. static void check_db_age()
  685. {
  686.     long age;
  687.     
  688.     if (max_age != -1) {
  689.     /* Requires existance of kerb_get_db_age() */
  690.     gettimeofday(&kerb_time, 0);
  691.     age = kerb_get_db_age();
  692.     if (age == 0) {
  693.         klog(L_KRB_PERR, "Database currently being updated!");
  694.         hang();
  695.     }
  696.     if ((age + max_age) < kerb_time.tv_sec) {
  697.         klog(L_KRB_PERR, "Database out of date!");
  698.         hang();
  699.         /* NOTREACHED */
  700.     }
  701.     }
  702. }
  703.  
  704. check_princ(p_name, instance, lifetime, p)
  705.     char   *p_name;
  706.     char   *instance;
  707.     unsigned lifetime;
  708.  
  709.     Principal *p;
  710. {
  711.     static int n;
  712.     static int more;
  713.     long trans;
  714.  
  715.     n = kerb_get_principal(p_name, instance, p, 1, &more);
  716.     klog(L_ALL_REQ,
  717.      "Principal: \"%s\", Instance: \"%s\" Lifetime = %d n = %d",
  718.      p_name, instance, lifetime, n, 0);
  719.     
  720.     if (n < 0) {
  721.     lt = klog(L_KRB_PERR, "Database unavailable!");
  722.     hang();
  723.     }
  724.     
  725.     /*
  726.      * if more than one p_name, pick one, randomly create a session key,
  727.      * compute maximum lifetime, lookup authorizations if applicable,
  728.      * and stuff into cipher. 
  729.      */
  730.     if (n == 0) {
  731.     /* service unknown, log error, skip to next request */
  732.     lt = klog(L_ERR_UNK, "UNKNOWN \"%s\" \"%s\"", p_name,
  733.         instance, 0);
  734.     return KERB_ERR_PRINCIPAL_UNKNOWN;
  735.     }
  736.     if (more) {
  737.     /* not unique, log error */
  738.     lt = klog(L_ERR_NUN, "Principal NOT UNIQUE \"%s\" \"%s\"",
  739.           p_name, instance, 0);
  740.     return KERB_ERR_PRINCIPAL_NOT_UNIQUE;
  741.     }
  742.     /* If the user's key is null, we want to return an error */
  743.     if ((p->key_low == 0) && (p->key_high == 0)) {
  744.     /* User has a null key */
  745.     lt = klog(L_ERR_NKY, "Null key \"%s\" \"%s\"", p_name,
  746.         instance, 0);
  747.     return KERB_ERR_NULL_KEY;
  748.     }
  749.     if (master_key_version != p->kdc_key_ver) {
  750.     /* log error reply */
  751.     lt = klog(L_ERR_MKV,
  752.         "Key vers incorrect, KRB = %d, \"%s\" \"%s\" = %d",
  753.         master_key_version, p->name, p->instance, p->kdc_key_ver,
  754.         0);
  755.     return KERB_ERR_NAME_MAST_KEY_VER;
  756.     }
  757.     /* make sure the service hasn't expired */
  758.     if ((u_long) p->exp_date < (u_long) kerb_time.tv_sec) {
  759.     /* service did expire, log it */
  760.     lt = klog(L_ERR_SEXP,
  761.         "EXPIRED \"%s\" \"%s\"  %s", p->name, p->instance,
  762.          stime(&(p->exp_date)), 0);
  763.     return KERB_ERR_NAME_EXP;
  764.     }
  765.     /* ok is zero */
  766.     return 0;
  767. }
  768.  
  769.  
  770. /* Set the key for krb_rd_req so we can check tgt */
  771. set_tgtkey(r)
  772.     char   *r;            /* Realm for desired key */
  773. {
  774.     int     n;
  775.     static char lastrealm[REALM_SZ];
  776.     Principal p_st;
  777.     Principal *p = &p_st;
  778.     C_Block key;
  779.  
  780.     if (!strcmp(lastrealm, r))
  781.     return (KSUCCESS);
  782.  
  783.     log("Getting key for %s", r);
  784.  
  785.     n = kerb_get_principal("krbtgt", r, p, 1, &more);
  786.     if (n == 0)
  787.     return (KFAILURE);
  788.  
  789.     /* unseal tgt key from master key */
  790.     bcopy(&p->key_low, key, 4);
  791.     bcopy(&p->key_high, ((long *) key) + 1, 4);
  792.     kdb_encrypt_key(key, key, master_key,
  793.             master_key_schedule, DECRYPT);
  794.     krb_set_key(key, 0);
  795.     strcpy(lastrealm, r);
  796.     return (KSUCCESS);
  797. }
  798.  
  799. static void
  800. hang()
  801. {
  802.     if (pause_int == -1) {
  803.     klog(L_KRB_PERR, "Kerberos will pause so as not to loop init");
  804.     for (;;)
  805.         pause();
  806.     } else {
  807.     char buf[256];
  808.     sprintf(buf,  "Kerberos will wait %d seconds before dying so as not to loop init", pause_int);
  809.     klog(L_KRB_PERR, buf);
  810.     sleep(pause_int);
  811.     klog(L_KRB_PERR, "Do svedania....\n");
  812.     exit(1);
  813.     }
  814. }
  815.