This commit was manufactured by cvs2svn to create tag
[krb5.git] / src / slave / kprop.c
index 9db09c493587be56ee3fbff603e689d5abf98824..fa32f11a8432b6492e4c9e2aca78c695a7c5f30a 100644 (file)
@@ -1,30 +1,33 @@
 /*
- * $Source$
- * $Author$
+ * slave/kprop.c
  *
  * Copyright 1990,1991 by the Massachusetts Institute of Technology.
  * All Rights Reserved.
  *
- * For copying and distribution information, please see the file
- * <krb5/copyright.h>.
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
  *
  */
 
-#if !defined(lint) && !defined(SABER)
-static char rcsid_kprop_c[] =
-"$Id$";
-#endif /* !lint && !SABER */
-
-#include <krb5/krb5.h>
-#include <krb5/asn1.h>
-#include <krb5/osconf.h>
-#include <krb5/kdb.h>
-#include <krb5/kdb_dbm.h>
-#include <krb5/ext-proto.h>
-#include <krb5/los-proto.h>
-#include <com_err.h>
-#include <errno.h>
 
+#include <errno.h>
 #include <stdio.h>
 #include <ctype.h>
 #include <sys/file.h>
@@ -37,58 +40,83 @@ static char rcsid_kprop_c[] =
 #include <netinet/in.h>
 #include <sys/param.h>
 #include <netdb.h>
+#include <fcntl.h>
 
+#include "k5-int.h"
+#include "com_err.h"
 #include "kprop.h"
 
 static char *kprop_version = KPROP_PROT_VERSION;
 
 char   *progname = 0;
 int     debug = 0;
+char   *srvtab = 0;
 char   *slave_host;
 char   *realm = 0;
 char   *file = KPROP_DEFAULT_FILE;
+short  port = 0;
 
 krb5_principal my_principal;           /* The Kerberos principal we'll be */
                                /* running under, initialized in */
                                /* get_tickets() */
 krb5_ccache    ccache;         /* Credentials cache which we'll be using */
-krb5_creds     my_creds;       /* My credentials */
-krb5_int32     my_seq_num;     /* Sequence number to use for connection */
-krb5_int32     his_seq_num;    /* Remote sequence number */
+/* krb5_creds  my_creds;       /* My credentials */
+krb5_creds     creds;
 krb5_address   sender_addr;
 krb5_address   receiver_addr;
 
-void   PRS();
-void   get_tickets();
-void   usage();
-krb5_error_code open_connection();
-void   kerberos_authenticate();
-int    open_database();
-void   xmit_database();
-void   send_error();
-void   update_last_prop_file();
+void   PRS
+       PROTOTYPE((int, char **));
+void   get_tickets
+       PROTOTYPE((krb5_context));
+static void usage 
+       PROTOTYPE((void));
+krb5_error_code open_connection 
+       PROTOTYPE((char *, int *, char *, int));
+void   kerberos_authenticate 
+       PROTOTYPE((krb5_context, krb5_auth_context *, 
+                  int, krb5_principal, krb5_creds **));
+int    open_database 
+       PROTOTYPE((krb5_context, char *, int *));
+void   close_database 
+       PROTOTYPE((krb5_context, int));
+void   xmit_database 
+       PROTOTYPE((krb5_context, krb5_auth_context, krb5_creds *, 
+                  int, int, int));
+void   send_error 
+       PROTOTYPE((krb5_context, krb5_creds *, int, char *, krb5_error_code));
+void   update_last_prop_file 
+       PROTOTYPE((char *, char *));
 
 static void usage()
 {
-       fprintf(stderr, "\nUsage: %s [-r realm] [-f file] [-d] slave_host\n\n",
+       fprintf(stderr, "\nUsage: %s [-r realm] [-f file] [-d] [-P port] [-s srvtab] slave_host\n\n",
                progname);
        exit(1);
 }
 
-void
+int
 main(argc, argv)
        int     argc;
        char    **argv;
 {
        int     fd, database_fd, database_size;
        krb5_error_code retval;
+       krb5_context context;
+       krb5_creds *my_creds;
+       krb5_auth_context auth_context;
        char    Errmsg[256];
        
-       PRS(argv);
-       get_tickets();
+       retval = krb5_init_context(&context);
+       if (retval) {
+               com_err(argv[0], retval, "while initializing krb5");
+               exit(1);
+       }
+       PRS(argc, argv);
+       get_tickets(context);
 
-       database_fd = open_database(file, &database_size);
-       if (retval = open_connection(slave_host, &fd, Errmsg)) {
+       database_fd = open_database(context, file, &database_size);
+       if (retval = open_connection(slave_host, &fd, Errmsg, sizeof(Errmsg))) {
                com_err(progname, retval, "%s while opening connection to %s",
                        Errmsg, slave_host);
                exit(1);
@@ -98,25 +126,25 @@ main(argc, argv)
                        progname, Errmsg, slave_host);
                exit(1);
        }
-       kerberos_authenticate(fd, my_principal);
-       if (debug) {
-               printf("My sequence number: %d\n", my_seq_num);
-               printf("His sequence number: %d\n", his_seq_num);
-       }
-       xmit_database(fd, database_fd, database_size);
+       kerberos_authenticate(context, &auth_context, fd, my_principal, 
+                             &my_creds);
+       xmit_database(context, auth_context, my_creds, fd, database_fd, 
+                     database_size);
        update_last_prop_file(slave_host, file);
        printf("Database propagation to %s: SUCCEEDED\n", slave_host);
+       krb5_free_cred_contents(context, my_creds);
+       close_database(context, database_fd);
        exit(0);
 }
 
-void PRS(argv)
+void PRS(argc, argv)
+       int     argc;
        char    **argv;
 {
        register char   *word, ch;
        
-       krb5_init_ets();
        progname = *argv++;
-       while (word = *argv++) {
+       while (--argc && (word = *argv++)) {
                if (*word == '-') {
                        word++;
                        while (word && (ch = *word++)) {
@@ -142,6 +170,24 @@ void PRS(argv)
                                case 'd':
                                        debug++;
                                        break;
+                               case 'P':
+                                       if (*word)
+                                               port = htons(atoi(word));
+                                       else
+                                               port = htons(atoi(*argv++));
+                                       if (!port)
+                                               usage();
+                                       word = 0;
+                                       break;
+                               case 's':
+                                       if (*word)
+                                               srvtab = word;
+                                       else
+                                               srvtab = *argv++;
+                                       if (!srvtab)
+                                               usage();
+                                       word = 0;
+                                       break;
                                default:
                                        usage();
                                }
@@ -158,51 +204,46 @@ void PRS(argv)
                usage();
 }
 
-void get_tickets()
+void get_tickets(context)
+    krb5_context context;
 {
        char   my_host_name[MAXHOSTNAMELEN];
        char   buf[BUFSIZ];
-       char   *cp, *strcpy(), *krb_get_phost();
+       char   *cp;
        struct hostent *hp;
-       krb5_address **my_addresses;
        krb5_error_code retval;
        static char tkstring[] = "/tmp/kproptktXXXXXX";
+       krb5_keytab keytab = NULL;
 
        /*
         * Figure out what tickets we'll be using to send stuff
         */
-       if (gethostname (my_host_name, sizeof(my_host_name)) != 0) { 
-               com_err(progname, errno, "while getting my hostname");
-               exit(1);
-       }
-       /* get canonicalized  service instance name */
-       if (!(hp = gethostbyname(my_host_name))) {
-               fprintf(stderr, "Couldn't get my cannonicalized host name!\n");
-               exit(1);
+       retval = krb5_sname_to_principal(context, NULL, NULL,
+                                        KRB5_NT_SRV_HST, &my_principal);
+       if (retval) {
+           com_err(progname, errno, "while setting client principal name");
+           exit(1);
        }
-       for (cp=hp->h_name; *cp; cp++)
-               if (isupper(*cp))
-                       *cp = tolower(*cp);
-       if (realm)
-               sprintf(buf, "rcmd/%s@%s", hp->h_name, realm);
-       else
-               sprintf(buf, "rcmd/%s", hp->h_name);
-       if (retval = krb5_parse_name(buf, &my_principal)) {
-               com_err (progname, retval, "when parsing name %s",buf);
-               exit(1);
+       if (realm) {
+           (void) krb5_xfree(krb5_princ_realm(context, my_principal)->data);
+           krb5_princ_set_realm_length(context, my_principal, strlen(realm));
+           krb5_princ_set_realm_data(context, my_principal, strdup(realm));
        }
+#if 0
+       krb5_princ_type(context, my_principal) = KRB5_NT_PRINCIPAL;
+#endif
 
        /*
         * Initialize cache file which we're going to be using
         */
        (void) mktemp(tkstring);
        sprintf(buf, "FILE:%s", tkstring);
-       if (retval = krb5_cc_resolve(buf, &ccache)) {
-               com_err(progname, retval, "while opening crednetials cache %s",
+       if (retval = krb5_cc_resolve(context, buf, &ccache)) {
+               com_err(progname, retval, "while opening credential cache %s",
                        buf);
                exit(1);
        }
-       if (retval = krb5_cc_initialize(ccache, my_principal)) {
+       if (retval = krb5_cc_initialize(context, ccache, my_principal)) {
                com_err (progname, retval, "when initializing cache %s",
                         buf);
                exit(1);
@@ -213,69 +254,64 @@ void get_tickets()
         *
         * Construct the principal name for the slave host.
         */
-       memset((char *)&my_creds, 0, sizeof(my_creds));
-       if (!(hp = gethostbyname(slave_host))) {
-               fprintf(stderr,
-                       "Couldn't get cannonicalized name for slave\n");
-               exit(1);
-       }
-       for (cp=hp->h_name; *cp; cp++)
-               if (isupper(*cp))
-                       *cp = tolower(*cp);
-       if (!(slave_host = malloc(strlen(hp->h_name) + 1))) {
-               com_err(progname, ENOMEM,
-                       "while allocate space for canonicalized slave host");
-               exit(1);
+       memset((char *)&creds, 0, sizeof(creds));
+       retval = krb5_sname_to_principal(context,
+                                        slave_host, KPROP_SERVICE_NAME,
+                                        KRB5_NT_SRV_HST, &creds.server);
+       if (retval) {
+           com_err(progname, errno, "while setting server principal name");
+           (void) krb5_cc_destroy(context, ccache);
+           exit(1);
        }
-       strcpy(slave_host, hp->h_name);
-       if (realm)
-               sprintf(buf, "%s/%s@%s", KPROP_SERVICE_NAME, slave_host,
-                       realm);
-       else
-               sprintf(buf, "%s/%s", KPROP_SERVICE_NAME, hp->h_name);
-       if (retval = krb5_parse_name(buf, &my_creds.server)) {
-               com_err(progname, retval,
-                       "while parsing slave principal name");
-               exit(1);
+       if (realm) {
+           (void) krb5_xfree(krb5_princ_realm(context, creds.server)->data);
+           krb5_princ_set_realm_length(context, creds.server, strlen(realm));
+           krb5_princ_set_realm_data(context, creds.server, strdup(realm));
        }
+
        /*
         * Now fill in the client....
         */
-       if (retval = krb5_copy_principal(my_principal, &my_creds.client)) {
+       if (retval = krb5_copy_principal(context, my_principal, &creds.client)) {
                com_err(progname, retval, "While copying client principal");
+               (void) krb5_cc_destroy(context, ccache);
                exit(1);
        }
-       /*
-        * Get my addresses
-        */
-       retval = krb5_os_localaddr(&my_addresses);
-       if (retval != 0) {
-               com_err(progname, retval,
-                       "when getting my address");
-               exit(1);
+       if (srvtab) {
+               if (retval = krb5_kt_resolve(context, srvtab, &keytab)) {
+                       com_err(progname, retval, "while resolving keytab");
+                       (void) krb5_cc_destroy(context, ccache);
+                       exit(1);
+               }
        }
-       retval = krb5_get_in_tkt_with_skey(0, my_addresses,
-                                          ETYPE_DES_CBC_CRC,
-                                          0, ccache, &my_creds);
+
+       retval = krb5_get_in_tkt_with_keytab(context, 0, 0, NULL,
+                                            NULL, keytab, ccache, &creds, 0);
        if (retval) {
-               com_err(progname, retval, "While getting initial ticket\n");
+               com_err(progname, retval, "while getting initial ticket\n");
+               (void) krb5_cc_destroy(context, ccache);
                exit(1);
        }
+
+       if (keytab)
+           (void) krb5_kt_close(context, keytab);
+       
        /*
         * Now destroy the cache right away --- the credentials we
         * need will be in my_creds.
         */
-       if (retval = krb5_cc_destroy(ccache)) {
+       if (retval = krb5_cc_destroy(context, ccache)) {
                com_err(progname, retval, "while destroying ticket cache");
                exit(1);
        }
 }
 
 krb5_error_code
-open_connection(host, fd, Errmsg)
+open_connection(host, fd, Errmsg, ErrmsgSz)
        char    *host;
        int     *fd;
        char    *Errmsg;
+       int      ErrmsgSz;
 {
        int     s;
        krb5_error_code retval;
@@ -291,16 +327,20 @@ open_connection(host, fd, Errmsg)
                *fd = -1;
                return(0);
        }
-       sp = getservbyname(KPROP_SERVICE, "tcp");
-       if (sp == 0) {
-               (void) strcpy(Errmsg, KPROP_SERVICE);
-               (void) strcat(Errmsg, "/tcp: unknown service");
-               *fd = -1;
-               return(0);
-       }
        sin.sin_family = hp->h_addrtype;
-       bcopy(hp->h_addr, (char *)&sin.sin_addr, hp->h_length);
-       sin.sin_port = sp->s_port;
+       memcpy((char *)&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr));
+       if(!port) {
+               sp = getservbyname(KPROP_SERVICE, "tcp");
+               if (sp == 0) {
+                       (void) strncpy(Errmsg, KPROP_SERVICE, ErrmsgSz - 1);
+                       Errmsg[ErrmsgSz - 1] = '\0';
+                       (void) strncat(Errmsg, "/tcp: unknown service", ErrmsgSz - 1 - strlen(Errmsg));
+                       *fd = -1;
+                       return(0);
+               }
+               sin.sin_port = sp->s_port;
+       } else
+               sin.sin_port = port;
        s = socket(AF_INET, SOCK_STREAM, 0);
        
        if (s < 0) {
@@ -325,10 +365,10 @@ open_connection(host, fd, Errmsg)
               sizeof(sin.sin_addr));
 
        socket_length = sizeof(sin);
-       if (getpeername(s, (struct sockaddr *)&sin, &socket_length) < 0) {
+       if (getsockname(s, (struct sockaddr *)&sin, &socket_length) < 0) {
                retval = errno;
                close(s);
-               (void) sprintf(Errmsg, "in call to getpeername");
+               (void) sprintf(Errmsg, "in call to getsockname");
                return(retval);
        }
        sender_addr.addrtype = ADDRTYPE_INET;
@@ -341,18 +381,33 @@ open_connection(host, fd, Errmsg)
 }
 
 
-void kerberos_authenticate(fd, me)
-       int     fd;
-       krb5_principal  me;
+void kerberos_authenticate(context, auth_context, fd, me, new_creds)
+    krb5_context context;
+    krb5_auth_context *auth_context;
+    int        fd;
+    krb5_principal me;
+    krb5_creds ** new_creds;
 {
        krb5_error_code retval;
        krb5_error      *error = NULL;
        krb5_ap_rep_enc_part    *rep_result;
 
-       if (retval = krb5_sendauth((void *)&fd, kprop_version, me,
-                                  my_creds.server, AP_OPTS_MUTUAL_REQUIRED,
-                                  NULL, &my_creds, NULL, &my_seq_num, NULL,
-                                  &error, &rep_result)) {
+    if (retval = krb5_auth_con_init(context, auth_context)) 
+       exit(1);
+
+    krb5_auth_con_setflags(context, *auth_context, 
+                          KRB5_AUTH_CONTEXT_DO_SEQUENCE);
+
+    if (retval = krb5_auth_con_setaddrs(context, *auth_context, &sender_addr,
+                                       &receiver_addr)) {
+       com_err(progname, retval, "in krb5_auth_con_setaddrs");
+       exit(1);
+    }
+
+       if (retval = krb5_sendauth(context, auth_context, (void *)&fd, 
+                                  kprop_version, me, creds.server,
+                                  AP_OPTS_MUTUAL_REQUIRED, NULL, &creds, NULL,
+                                  &error, &rep_result, new_creds)) {
                com_err(progname, retval, "while authenticating to server");
                if (error) {
                        if (error->error == KRB_ERR_GENERIC) {
@@ -369,14 +424,14 @@ void kerberos_authenticate(fd, me)
                                                "Error text from server: %s\n",
                                                error->text.data);
                        }
-                       krb5_free_error(error);
+                       krb5_free_error(context, error);
                }
                exit(1);
        }
-       his_seq_num = rep_result->seq_number;
-       krb5_free_ap_rep_enc_part(rep_result);
+       krb5_free_ap_rep_enc_part(context, rep_result);
 }
 
+char * dbpathname;
 /*
  * Open the Kerberos database dump file.  Takes care of locking it
  * and making sure that the .ok file is more recent that the database
@@ -386,26 +441,39 @@ void kerberos_authenticate(fd, me)
  * in the size of the database file.
  */
 int
-open_database(data_fn, size)
-       char    *data_fn;
-       int     *size;
+open_database(context, data_fn, size)
+    krb5_context context;
+    char *data_fn;
+    int        *size;
 {
        int             fd;
+       int             err;
        struct stat     stbuf, stbuf_ok;
        char            *data_ok_fn;
        static char ok[] = ".dump_ok";
-       
-       if ((fd = open(data_fn, O_RDONLY)) < 0) {
-               com_err(progname, 0, "While trying to open %s",
-                       data_fn);
-               exit(1);
-       }
-       if (flock(fd, LOCK_SH | LOCK_NB)) {
-               com_err(progname, errno, "while trying to flock %s",
-                       data_fn);
+
+       dbpathname = strdup(data_fn);
+       if (!dbpathname) {
+           com_err(progname, ENOMEM, "allocating database file name '%s'",
+                   data_fn);
+           exit(1);
+       }
+       if ((fd = open(dbpathname, O_RDONLY)) < 0) {
+               com_err(progname, errno, "while trying to open %s",
+                       dbpathname);
                exit(1);
        }
-       if (stat(data_fn, &stbuf)) {
+
+       err = krb5_lock_file(context, fd,
+                            KRB5_LOCKMODE_SHARED|KRB5_LOCKMODE_DONTBLOCK);
+       if (err == EAGAIN || err == EWOULDBLOCK || errno == EACCES) {
+           com_err(progname, 0, "database locked");
+           exit(1);
+       } else if (err) {
+           com_err(progname, err, "while trying to lock '%s'", dbpathname);
+           exit(1);
+       }           
+       if (fstat(fd, &stbuf)) {
                com_err(progname, errno, "while trying to stat %s",
                        data_fn);
                exit(1);
@@ -415,7 +483,8 @@ open_database(data_fn, size)
                com_err(progname, ENOMEM, "while trying to malloc data_ok_fn");
                exit(1);
        }
-       strcat(strcpy(data_ok_fn, data_fn), ok);
+       strcpy(data_ok_fn, data_fn);
+       strcat(data_ok_fn, ok);
        if (stat(data_ok_fn, &stbuf_ok)) {
                com_err(progname, errno, "while trying to stat %s",
                        data_ok_fn);
@@ -432,6 +501,19 @@ open_database(data_fn, size)
        return(fd);
 }
 
+void
+close_database(context, fd)
+    krb5_context context;
+    int fd;
+{
+    int err;
+    if (err = krb5_lock_file(context, fd, KRB5_LOCKMODE_UNLOCK))
+       com_err(progname, err, "while unlocking database '%s'", dbpathname);
+    free(dbpathname);
+    (void)close(fd);
+    return;
+}
+  
 /*
  * Now we send over the database.  We use the following protocol:
  * Send over a KRB_SAFE message with the size.  Then we send over the
@@ -442,15 +524,17 @@ open_database(data_fn, size)
  * will abort the entire operation.
  */
 void
-xmit_database(fd, database_fd, database_size)
-       int     fd;
-       int     database_fd;
-       int     database_size;
+xmit_database(context, auth_context, my_creds, fd, database_fd, database_size)
+    krb5_context context;
+    krb5_auth_context auth_context;
+    krb5_creds *my_creds;
+    int        fd;
+    int        database_fd;
+    int        database_size;
 {
-       int     send_size, sent_size, n, eblock_size;
+       krb5_int32      send_size, sent_size, n;
        krb5_data       inbuf, outbuf;
        char            buf[KPROP_BUFSIZ];
-       char            *i_vector;
        krb5_error_code retval;
        krb5_error      *error;
        
@@ -460,35 +544,28 @@ xmit_database(fd, database_fd, database_size)
        send_size = htonl(database_size);
        inbuf.data = (char *) &send_size;
        inbuf.length = sizeof(send_size); /* must be 4, really */
-       if (retval = krb5_mk_safe(&inbuf, KPROP_CKSUMTYPE,
-                                 &my_creds.keyblock, 
-                                 &sender_addr, &receiver_addr,
-                                 my_seq_num++,
-                                 KRB5_PRIV_DOSEQUENCE|KRB5_SAFE_NOTIME,
-                                 0,    /* no rcache when NOTIME */
-                                 &outbuf)) {
+       /* KPROP_CKSUMTYPE */
+       if (retval = krb5_mk_safe(context, auth_context, &inbuf, 
+                                 &outbuf, NULL)) {
                com_err(progname, retval, "while encoding database size");
-               send_error(fd, "while encoding database size", retval);
+               send_error(context, my_creds, fd, "while encoding database size", retval);
                exit(1);
        }
-       if (retval = krb5_write_message((void *) &fd, &outbuf)) {
-               xfree(outbuf.data);
+       if (retval = krb5_write_message(context, (void *) &fd, &outbuf)) {
+               krb5_free_data_contents(context, &outbuf);
                com_err(progname, retval, "while sending database size");
                exit(1);
        }
-       xfree(outbuf.data);
-       /*
-        * Initialize the initial vector.
-        */
-       eblock_size = krb5_keytype_array[my_creds.keyblock.keytype]->
-               system->block_length;
-       if (!(i_vector=malloc(eblock_size))) {
-               com_err(progname, ENOMEM, "while allocating i_vector");
-               send_error(fd, "malloc failed while allocating i_vector",
-                          ENOMEM);
-               exit(1);
-       }
-       memset(i_vector, 0, eblock_size);
+       krb5_free_data_contents(context, &outbuf);
+    /*
+     * Initialize the initial vector.
+     */
+    if (retval = krb5_auth_con_initivector(context, auth_context)) {
+       send_error(context, my_creds, fd, 
+                  "failed while initializing i_vector", retval);
+       com_err(progname, retval, "while allocating i_vector");
+       exit(1);
+    }
        /*
         * Send over the file, block by block....
         */
@@ -496,37 +573,30 @@ xmit_database(fd, database_fd, database_size)
        sent_size = 0;
        while (n = read(database_fd, buf, sizeof(buf))) {
                inbuf.length = n;
-               if (retval = krb5_mk_priv(&inbuf, ETYPE_DES_CBC_CRC,
-                                         &my_creds.keyblock,
-                                         &sender_addr,
-                                         &receiver_addr,
-                                         my_seq_num++,
-                                         KRB5_PRIV_DOSEQUENCE|KRB5_PRIV_NOTIME,
-                                         0, /* again, no rcache */
-                                         i_vector,
-                                         &outbuf)) {
+               if (retval = krb5_mk_priv(context, auth_context, &inbuf,
+                                         &outbuf, NULL)) {
                        sprintf(buf,
                                "while encoding database block starting at %d",
                                sent_size);
                        com_err(progname, retval, buf);
-                       send_error(fd, buf, retval);
+                       send_error(context, my_creds, fd, buf, retval);
                        exit(1);
                }
-               if (retval = krb5_write_message((void *) &fd, &outbuf)) {
-                       xfree(outbuf.data);
+               if (retval = krb5_write_message(context, (void *)&fd,&outbuf)) {
+                       krb5_free_data_contents(context, &outbuf);
                        com_err(progname, retval,
                                "while sending database block starting at %d",
                                sent_size);
                        exit(1);
                }
-               xfree(outbuf.data);
+               krb5_free_data_contents(context, &outbuf);
                sent_size += n;
                if (debug)
                        printf("%d bytes sent.\n", sent_size);
        }
        if (sent_size != database_size) {
                com_err(progname, 0, "Premature EOF found for database file!");
-               send_error(fd, "Premature EOF found for database file!",
+               send_error(context, my_creds, fd,"Premature EOF found for database file!",
                           KRB5KRB_ERR_GENERIC);
                exit(1);
        }
@@ -534,7 +604,7 @@ xmit_database(fd, database_fd, database_size)
         * OK, we've sent the database; now let's wait for a success
         * indication from the remote end.
         */
-       if (retval = krb5_read_message((void *) &fd, &inbuf)) {
+       if (retval = krb5_read_message(context, (void *) &fd, &inbuf)) {
                com_err(progname, retval,
                        "while reading response from server");
                exit(1);
@@ -544,7 +614,7 @@ xmit_database(fd, database_fd, database_size)
         * the error message
         */
        if (krb5_is_krb_error(&inbuf)) {
-               if (retval = krb5_rd_error(&inbuf, &error)) {
+               if (retval = krb5_rd_error(context, &inbuf, &error)) {
                        com_err(progname, retval,
                                "while decoding error response from server");
                        exit(1);
@@ -562,13 +632,10 @@ xmit_database(fd, database_fd, database_size)
                                        "Error text from server: %s\n",
                                        error->text.data);
                }
-               krb5_free_error(error);
+               krb5_free_error(context, error);
                exit(1);
        }
-       if (retval = krb5_rd_safe(&inbuf, &my_creds.keyblock, &receiver_addr,
-                                 &sender_addr, his_seq_num++,
-                                 KRB5_SAFE_DOSEQUENCE|KRB5_SAFE_NOTIME,
-                                 0, &outbuf)) {
+       if (retval = krb5_rd_safe(context,auth_context,&inbuf,&outbuf,NULL)) {
                com_err(progname, retval,
                        "while decoding final size packet from server");
                exit(1);
@@ -586,18 +653,20 @@ xmit_database(fd, database_fd, database_size)
 }
 
 void
-send_error(fd, err_text, err_code)
-       int     fd;
-       char    *err_text;
-       krb5_error_code err_code;
+send_error(context, my_creds, fd, err_text, err_code)
+    krb5_context context;
+    krb5_creds *my_creds;
+    int        fd;
+    char       *err_text;
+    krb5_error_code    err_code;
 {
        krb5_error      error;
        const char      *text;
        krb5_data       outbuf;
 
        memset((char *)&error, 0, sizeof(error));
-       krb5_us_timeofday(&error.ctime, &error.cusec);
-       error.server = my_creds.server;
+       krb5_us_timeofday(context, &error.ctime, &error.cusec);
+       error.server = my_creds->server;
        error.client = my_principal;
        error.error = err_code - ERROR_TABLE_BASE_krb5;
        if (error.error > 127)
@@ -609,9 +678,9 @@ send_error(fd, err_text, err_code)
        error.text.length = strlen(text) + 1;
        if (error.text.data = malloc(error.text.length)) {
                strcpy(error.text.data, text);
-               if (!krb5_mk_error(&error, &outbuf)) {
-                       (void) krb5_write_message((void *) &fd, &outbuf);
-                       xfree(outbuf.data);
+               if (!krb5_mk_error(context, &error, &outbuf)) {
+                       (void) krb5_write_message(context, (void *)&fd,&outbuf);
+                       krb5_free_data_contents(context, &outbuf);
                }
                free(error.text.data);
        }
@@ -637,13 +706,14 @@ void update_last_prop_file(hostname, file_name)
        strcat(file_last_prop, ".");
        strcat(file_last_prop, hostname);
        strcat(file_last_prop, last_prop);
-       if ((fd = open(file_last_prop, O_WRONLY|O_CREAT|O_TRUNC, 0600)) < 0) {
+       if ((fd = THREEPARAMOPEN(file_last_prop, O_WRONLY|O_CREAT|O_TRUNC, 0600)) < 0) {
                com_err(progname, errno,
                        "while creating 'last_prop' file, '%s'",
                        file_last_prop);
                free(file_last_prop);
                return;
        }
+       write(fd, "", 1);
        free(file_last_prop);
        close(fd);
        return;