home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / libexec / kpasswdd / kpasswdd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-12  |  7.2 KB  |  272 lines

  1. /*-
  2.  * Copyright (c) 1990 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33.  
  34. #ifndef lint
  35. char copyright[] =
  36. "@(#) Copyright (c) 1990 The Regents of the University of California.\n\
  37.  All rights reserved.\n";
  38. #endif /* not lint */
  39.  
  40. #ifndef lint
  41. static char sccsid[] = "@(#)kpasswdd.c    5.1 (Berkeley) 4/12/91";
  42. #endif /* not lint */
  43.  
  44. /*
  45.  * kpasswdd - update a principal's passwd field in the Kerberos
  46.  *           database.  Called from inetd.
  47.  * K. Fall
  48.  * 12-Dec-88
  49.  */
  50.  
  51. #include <sys/types.h>
  52. #include <sys/time.h>
  53. #include <sys/resource.h>
  54. #include <sys/signal.h>
  55. #include <netinet/in.h>
  56. #include <pwd.h>
  57. #include <syslog.h>
  58. #include <kerberosIV/des.h>
  59. #include <kerberosIV/krb.h>
  60. #include <kerberosIV/krb_db.h>
  61. #include <stdio.h>
  62. #include "kpasswd_proto.h"
  63.  
  64. static    struct kpasswd_data    kpwd_data;
  65. static    des_cblock        master_key, key;
  66. static    Key_schedule        master_key_schedule,
  67.                 key_schedule, random_sched;
  68. long                mkeyversion;
  69. AUTH_DAT            kdata;
  70. static    Principal        principal_data;
  71. static    struct update_data    ud_data;
  72.  
  73. char                inst[INST_SZ];
  74. char                version[9];
  75. KTEXT_ST            ticket;
  76.  
  77. char    *progname;        /* for the library */
  78.  
  79. main()
  80. {
  81.     struct    sockaddr_in    foreign;
  82.     int            foreign_len = sizeof(foreign);
  83.     int            rval, more;
  84.     static  char    name[] = "kpasswdd";
  85.  
  86.     static    struct rlimit    rl = { 0, 0 };
  87.  
  88.     progname = name;
  89.     openlog("kpasswdd", LOG_CONS | LOG_PID, LOG_AUTH);
  90.  
  91.     signal(SIGHUP, SIG_IGN);
  92.     signal(SIGINT, SIG_IGN);
  93.     signal(SIGTSTP, SIG_IGN);
  94.     if (setrlimit(RLIMIT_CORE, &rl) < 0) {
  95.         syslog(LOG_ERR, "setrlimit: %m");
  96.         exit(1);
  97.     }
  98.  
  99.     if (getpeername(0, &foreign, &foreign_len) < 0) {
  100.         syslog(LOG_ERR,"getpeername: %m");
  101.         exit(1);
  102.     }
  103.  
  104.     strcpy(inst, "*");
  105.     rval = krb_recvauth(
  106.         0L,                /* options--!MUTUAL */
  107.         0,                /* file desc */
  108.         &ticket,            /* client's ticket */
  109.         SERVICE,            /* expected service */
  110.         inst,                /* expected instance */
  111.         &foreign,            /* foreign addr */
  112.         (struct sockaddr_in *) 0,    /* local addr */
  113.         &kdata,                /* returned krb data */
  114.         "",                /* service keys file */
  115.         (bit_64 *) NULL,        /* returned key schedule */
  116.         version
  117.     );
  118.  
  119.  
  120.     if (rval != KSUCCESS) {
  121.         syslog(LOG_NOTICE, "krb_recvauth: %s", krb_err_txt[rval]);
  122.         cleanup();
  123.         exit(1);
  124.     }
  125.  
  126.     if (*version == '\0') {
  127.         /* indicates error on client's side (no tickets, etc.) */
  128.         cleanup();
  129.         exit(0);
  130.     } else if (strcmp(version, "KPWDV0.1") != 0) {
  131.         syslog(LOG_NOTICE,
  132.             "kpasswdd version conflict (recv'd %s)",
  133.             version);
  134.         cleanup();
  135.         exit(1);
  136.     }
  137.  
  138.  
  139.     /* get master key */
  140.     if (kdb_get_master_key(0, master_key, master_key_schedule) != 0) {
  141.         syslog(LOG_ERR, "couldn't get master key");
  142.         cleanup();
  143.         exit(1);
  144.     }
  145.  
  146.     mkeyversion = kdb_get_master_key(NULL, master_key, master_key_schedule);
  147.  
  148.     if (mkeyversion < 0) {
  149.         syslog(LOG_NOTICE, "couldn't verify master key");
  150.         cleanup();
  151.         exit(1);
  152.     }
  153.  
  154.     /* get principal info */
  155.     rval = kerb_get_principal(
  156.         kdata.pname,
  157.         kdata.pinst,
  158.         &principal_data,
  159.         1,
  160.         &more
  161.     );
  162.  
  163.     if (rval < 0) {
  164.         syslog(LOG_NOTICE,
  165.             "error retrieving principal record for %s.%s",
  166.             kdata.pname, kdata.pinst);
  167.         cleanup();
  168.         exit(1);
  169.     }
  170.  
  171.     if (rval != 1 || (more != 0)) {
  172.         syslog(LOG_NOTICE, "more than 1 dbase entry for %s.%s",
  173.             kdata.pname, kdata.pinst);
  174.         cleanup();
  175.         exit(1);
  176.     }
  177.  
  178.     /* get the user's key */
  179.  
  180.     bcopy(&principal_data.key_low, key, 4);
  181.     bcopy(&principal_data.key_high, ((long *) key) + 1, 4);
  182.     kdb_encrypt_key(key, key, master_key, master_key_schedule,
  183.         DECRYPT);
  184.     key_sched(key, key_schedule);
  185.     des_set_key(key, key_schedule);
  186.  
  187.  
  188.     /* get random key and send it over {random} Kperson */
  189.  
  190.     random_key(kpwd_data.random_key);
  191.     strcpy(kpwd_data.secure_msg, SECURE_STRING);
  192.     if (des_write(0, &kpwd_data, sizeof(kpwd_data)) != sizeof(kpwd_data)) {
  193.         syslog(LOG_NOTICE, "error writing initial data");
  194.         cleanup();
  195.         exit(1);
  196.     }
  197.  
  198.     bzero(key, sizeof(key));
  199.     bzero(key_schedule, sizeof(key_schedule));
  200.  
  201.     /* now read update info: { info }Krandom */
  202.  
  203.     key_sched(kpwd_data.random_key, random_sched);
  204.     des_set_key(kpwd_data.random_key, random_sched);
  205.     if (des_read(0, &ud_data, sizeof(ud_data)) != sizeof(ud_data)) {
  206.         syslog(LOG_NOTICE, "update aborted");
  207.         cleanup();
  208.         exit(1);
  209.     }
  210.  
  211.     /* validate info string by looking at the embedded string */
  212.  
  213.     if (strcmp(ud_data.secure_msg, SECURE_STRING) != 0) {
  214.         syslog(LOG_NOTICE, "invalid update from %s",
  215.             inet_ntoa(foreign.sin_addr));
  216.         cleanup();
  217.         exit(1);
  218.     }
  219.  
  220.     /* produce the new key entry in the database { key }Kmaster */
  221.     string_to_key(ud_data.pw, key);
  222.     kdb_encrypt_key(key, key,
  223.         master_key, master_key_schedule,
  224.         ENCRYPT);
  225.     bcopy(key, &principal_data.key_low, 4);
  226.     bcopy(((long *) key) + 1,
  227.         &principal_data.key_high, 4);
  228.     bzero(key, sizeof(key));
  229.     principal_data.key_version++;
  230.     if (kerb_put_principal(&principal_data, 1)) {
  231.         syslog(LOG_ERR, "couldn't write new record for %s.%s",
  232.             principal_data.name, principal_data.instance);
  233.         cleanup();
  234.         exit(1);
  235.     }
  236.  
  237.     syslog(LOG_NOTICE,"wrote new password field for %s.%s from %s",
  238.         principal_data.name,
  239.         principal_data.instance,
  240.         inet_ntoa(foreign.sin_addr)
  241.     );
  242.  
  243.     send_ack(0, "Update complete.\n");
  244.     cleanup();
  245.     exit(0);
  246. }
  247.  
  248. cleanup()
  249. {
  250.     bzero(&kpwd_data, sizeof(kpwd_data));
  251.     bzero(master_key, sizeof(master_key));
  252.     bzero(master_key_schedule, sizeof(master_key_schedule));
  253.     bzero(key, sizeof(key));
  254.     bzero(key_schedule, sizeof(key_schedule));
  255.     bzero(random_sched, sizeof(random_sched));
  256.     bzero(&principal_data, sizeof(principal_data));
  257.     bzero(&ud_data, sizeof(ud_data));
  258. }
  259.  
  260. send_ack(remote, msg)
  261.     int    remote;
  262.     char    *msg;
  263. {
  264.     int    cc;
  265.     cc = des_write(remote, msg, strlen(msg) + 1);
  266.     if (cc <= 0) {
  267.         syslog(LOG_NOTICE, "error writing ack");
  268.         cleanup();
  269.         exit(1);
  270.     }
  271. }
  272.