--- /dev/null
+# Sanitize.in for Kerberos V5
+
+# Each directory to survive it's way into a release will need a file
+# like this one called "./.Sanitize". All keyword lines must exist,
+# and must exist in the order specified by this file. Each directory
+# in the tree will be processed, top down, in the following order.
+
+# Hash started lines like this one are comments and will be deleted
+# before anything else is done. Blank lines will also be squashed
+# out.
+
+# The lines between the "Do-first:" line and the "Things-to-keep:"
+# line are executed as a /bin/sh shell script before anything else is
+# done in this
+
+Do-first:
+
+# All files listed between the "Things-to-keep:" line and the
+# "Files-to-sed:" line will be kept. All other files will be removed.
+# Directories listed in this section will have their own Sanitize
+# called. Directories not listed will be removed in their entirety
+# with rm -rf.
+
+Things-to-keep:
+
+.cvsignore
+Makefile.in
+client
+configure
+configure.in
+kpasswd
+server
+v4server
+
+Things-to-lose:
+
+Do-last:
+
+# End of file.
--- /dev/null
+CFLAGS = $(CCOPTS)
+LDFLAGS = -g
+
+all::
+
--- /dev/null
+# Sanitize.in for Kerberos V5
+
+# Each directory to survive it's way into a release will need a file
+# like this one called "./.Sanitize". All keyword lines must exist,
+# and must exist in the order specified by this file. Each directory
+# in the tree will be processed, top down, in the following order.
+
+# Hash started lines like this one are comments and will be deleted
+# before anything else is done. Blank lines will also be squashed
+# out.
+
+# The lines between the "Do-first:" line and the "Things-to-keep:"
+# line are executed as a /bin/sh shell script before anything else is
+# done in this
+
+Do-first:
+
+# All files listed between the "Things-to-keep:" line and the
+# "Files-to-sed:" line will be kept. All other files will be removed.
+# Directories listed in this section will have their own Sanitize
+# called. Directories not listed will be removed in their entirety
+# with rm -rf.
+
+Things-to-keep:
+
+.cvsignore
+ChangeLog
+Makefile.in
+configure
+configure.in
+kadmin.M
+kadmin.c
+kadmin_add.c
+kadmin_adr.c
+kadmin_cpr.c
+kadmin_cpw.c
+kadmin_del.c
+kadmin_done.c
+kadmin_inq.c
+kadmin_mod.c
+kadmin_msnd.c
+
+Things-to-lose:
+
+Do-last:
+
+# End of file.
--- /dev/null
+Thu Apr 20 18:18:48 1995 Mark Eichin <eichin@cygnus.com>
+
+ Changes from Ian Taylor <ian@cygnus.com> to support testsuite.
+ Support -p port argument to kadmin client.
+ * kadmin.c (main): parse -p argument.
+ (adm5_init_link): new port argument, use it in preference to
+ getservbyname.
+ (usage): document new -p argument.
+
+Thu Apr 20 11:45:10 1995 <tytso@rsx-11.mit.edu>
+
+ * kadmin.c, kadmin_add.c, kadmin_adr.c, kadmin_cpr.c kadmin_cpw.c,
+ kadmin_del.c, kadmin_done.c, kadmin_inq.c, kadmin_mod.c,
+ kadmin_msnd.c: Add include of adm_defs.h, since that's no longer
+ included by krb5.h.
+
+Fri Mar 17 15:36:07 1995 Chris Provenzano (proven@mit.edu)
+
+ * kadmin_inq.c, kadmin.c:
+ Cast malloc() return value to shut compiler up.
+
+Fri Mar 10 11:09:34 1995 Chris Provenzano (proven@mit.edu)
+
+ * kadmin.c, kadmin_adr.c, kadmin_cpw.c, kadmin_done.c, kadmin_mod.c
+ * kadmin_add.c, kadmin_cpr.c, kadmin_del.c, kadmin_inq.c, kadmin_msnd.c
+ Use new calling convention for krb5_sendauth(), krb5_mk_priv(),
+ krb5_rd_priv(), krb5_mk_safe(), and krb5_rd_safe().
+
+Thu Mar 2 12:24:25 1995 Theodore Y. Ts'o <tytso@dcl>
+
+ * Makefile.in (ISODELIB): Remove reference to $(ISODELIB).
+
+Wed Mar 1 16:29:19 1995 Theodore Y. Ts'o <tytso@dcl>
+
+ * configure.in: Remove ISODE_INCLUDE, replace check for -lsocket
+ and -lnsl with WITH_NETLIB check.
+
+Tue Feb 28 02:18:37 1995 John Gilmore (gnu at toad.com)
+
+ * *.c: Avoid <krb5/...> and <com_err.h> includes.
+
+Tue Feb 14 15:30:55 1995 Chris Provenzano (proven@mit.edu)
+
+ * kadmin.c Call krb5_sendauth() with new calling convention
+
+Fri Feb 10 17:50:39 1995 Theodore Y. Ts'o <tytso@dcl>
+
+ * kadmin_msnd.c: Remove needless #include of <krb5/asn.1/encode.h>
+
+Mon Feb 06 17:19:04 1995 Chris Provenzano (proven@mit.edu)
+
+ * kadmin.c: Removed krb5_keytype, changed krb5_enctype to
+ krb5_enctype *, changed krb5_preauthtype to krb5_preauthtype *
+ for krb5_get_in_tkt_with_password() rotuine.
+
+Fri Feb 3 03:03:27 1995 John Gilmore <gnu@cygnus.com>
+
+ * kadmin.c (main): Real live non-kludged argument parsing.
+ Add -c option to specify ticket cache location (it really
+ should just use a cache in memory in the process, but that
+ isn't written yet). Make some error messages more explicit!
+
+Wed Jan 25 16:54:40 1995 Chris Provenzano (proven@mit.edu)
+
+ * Removed all narrow types and references to wide.h and narrow.h
+
+Fri Jan 13 15:23:47 1995 Chris Provenzano (proven@mit.edu)
+
+ * Added krb5_context to all krb5_routines
+
+Mon Oct 3 19:12:43 1994 Theodore Y. Ts'o (tytso@dcl)
+
+ * Makefile.in: Use $(srcdir) to find manual page for make install.
+
+Thu Sep 29 22:39:10 1994 Theodore Y. Ts'o (tytso@dcl)
+
+ * Makefile.in: relink executable if libraries change
+
+Thu Sep 15 16:49:19 1994 Theodore Y. Ts'o (tytso@dcl)
+
+ * kadm_add.c (kadm_add_user): Don't chop off last character of
+ principal if it was supplied by the caller (instead of
+ prompting the user to enter a principal).
+
+Wed Sep 14 22:20:46 1994 Theodore Y. Ts'o (tytso@dcl)
+
+ * kadmin_add.c (kadm_add_user): removed a duplicated
+ free(inbuf.data) call.
+
+Sat Jul 16 02:47:38 1994 Tom Yu (tlyu at dragons-lair)
+
+ * kadmin.c (get_first_ticket): change error code to match
+
+Fri Jun 24 22:48:29 1994 Theodore Y. Ts'o (tytso at tsx-11)
+
+ * kadmin_done (kadm_done): fix memory allocation bugs
+
+
--- /dev/null
+CFLAGS = $(CCOPTS) $(DEFS) $(LOCALINCLUDE)
+LDFLAGS = -g
+
+COMERRLIB=$(BUILDTOP)/util/et/libcom_err.a
+SSLIB=$(BUILDTOP)/util/ss/libss.a
+DBMLIB=
+KDBLIB=$(TOPLIBD)/libkdb5.a
+
+all::
+
+KLIB = $(TOPLIBD)/libkrb5.a $(TOPLIBD)/libcrypto.a $(SSLIB) $(COMERRLIB) $(DBMLIB)
+DEPKLIB = $(TOPLIBD)/libkrb5.a $(TOPLIBD)/libcrypto.a $(SSLIB) $(COMERRLIB) $(DBMLIB)
+
+SRCS = \
+ $(srcdir)/kadmin.c \
+ $(srcdir)/kadmin_add.c \
+ $(srcdir)/kadmin_adr.c \
+ $(srcdir)/kadmin_cpr.c \
+ $(srcdir)/kadmin_inq.c \
+ $(srcdir)/kadmin_msnd.c \
+ $(srcdir)/kadmin_mod.c \
+ $(srcdir)/kadmin_cpw.c \
+ $(srcdir)/kadmin_del.c \
+ $(srcdir)/kadmin_done.c
+
+OBJS = \
+ kadmin.o \
+ kadmin_add.o \
+ kadmin_adr.o \
+ kadmin_cpr.o \
+ kadmin_inq.o \
+ kadmin_msnd.o \
+ kadmin_mod.o \
+ kadmin_cpw.o \
+ kadmin_del.o \
+ kadmin_done.o
+
+all:: kadmin
+
+kadmin: $(KDBDEPLIB) $(OBJS) $(DEPKLIB)
+ $(CC) $(CFLAGS) -o kadmin $(OBJS) $(KLIB) $(LIBS)
+
+install::
+ $(INSTALL_PROGRAM) kadmin ${DESTDIR}$(CLIENT_BINDIR)/kadmin
+ $(INSTALL_DATA) $(srcdir)/kadmin.M ${DESTDIR}$(CLIENT_MANDIR)/kadmin.1
+
+clean::
+ $(RM) kadmin
+
--- /dev/null
+AC_INIT(kadmin.c)
+WITH_CCOPTS
+CONFIG_RULES
+AC_SET_BUILDTOP
+AC_PROG_INSTALL
+WITH_NETLIB
+ET_RULES
+KRB_INCLUDE
+WITH_KRB5ROOT
+V5_AC_OUTPUT_MAKEFILE
--- /dev/null
+.\" this file was somehow lost
+.\" but CVS deals badly with 0 length files.
--- /dev/null
+/*
+ * kadmin/client/kadmin.c
+ *
+ * Copyright 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ *
+ */
+
+/*
+ * Sandia National Laboratories also makes no representations about the
+ * suitability of the modifications, or additions to this software for
+ * any purpose. It is provided "as is" without express or implied warranty.
+ */
+
+
+/*
+ * kadmin
+ * Perform Remote Kerberos Administrative Functions
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <signal.h>
+#include <string.h>
+#include <pwd.h>
+#include "com_err.h"
+
+#ifndef MAXPATHLEN
+#define MAXPATHLEN 1024
+#endif
+
+#include "krb5.h"
+#include "adm_defs.h"
+
+static krb5_error_code get_first_ticket
+ PROTOTYPE((krb5_context,
+ krb5_ccache,
+ krb5_principal,
+ krb5_creds *));
+
+struct sockaddr_in local_sin, remote_sin;
+
+char cache_name[255] = "";
+
+static void get_def_princ
+ PROTOTYPE((krb5_context,
+ krb5_principal * ));
+
+void decode_kadmind_reply();
+int print_status_message();
+extern char *optarg;
+extern int optind;
+
+
+void
+main(argc,argv)
+ int argc;
+ char *argv[];
+{
+ krb5_ccache cache = NULL;
+
+ krb5_address local_addr, foreign_addr;
+
+ krb5_principal client;
+
+ char *client_name; /* Single string representation of client id */
+
+ krb5_data *requested_realm;
+ krb5_creds my_creds;
+
+ krb5_error_code retval; /* return code */
+
+ int local_socket;
+
+ krb5_error *err_ret;
+ krb5_ap_rep_enc_part *rep_ret;
+
+ kadmin_requests rd_priv_resp;
+
+ krb5_context context;
+ krb5_data msg_data, inbuf;
+ char buffer[255];
+ char command_type[120];
+ char princ_name[120];
+ int i, valid;
+ int option;
+ int oper_type;
+ int nflag = 0;
+ int port = 0;
+
+ krb5_auth_context * new_auth_context;
+ krb5_replay_data replaydata;
+
+ krb5_init_context(&context);
+ krb5_init_ets(context);
+
+ client_name = (char *) malloc(755);
+ memset((char *) client_name, 0, sizeof(client_name));
+
+ while ((option = getopt(argc, argv, "c:np:")) != EOF) {
+ switch (option) {
+ case 'c':
+ strcpy (cache_name, optarg);
+ break;
+ case 'n':
+ nflag++;
+ break;
+ case 'p':
+ port = htons(atoi(optarg));
+ break;
+ case '?':
+ default:
+ usage();
+ break;
+ }
+ }
+
+ if (optind < argc) {
+ /* Admin name specified on command line */
+ strcpy(client_name, argv[optind++]);
+ if (retval = krb5_parse_name(context, client_name, &client)) {
+ fprintf(stderr, "Error Parsing %s\n", client_name);
+ usage();
+ }
+ }
+ else {
+ /* Admin name should be defaulted */
+ get_def_princ(context, &client);
+ if (retval = krb5_unparse_name(context, client, &client_name)) {
+ fprintf(stderr, "Unable to unparse default administrator name!\n");
+ usage();
+ }
+ }
+
+ /* At this point, both client and client_name are set up. */
+
+ if (!nflag) {
+ strcpy(client_name, client->data[0].data);
+ strncat(client_name, "/admin@", 7);
+ strncat(client_name, client->realm.data, client->realm.length);
+ if (retval = krb5_parse_name(context, client_name, &client)) {
+ fprintf(stderr, "Unable to Parse %s\n", client_name);
+ usage();
+ }
+ }
+
+ if (optind < argc)
+ usage();
+
+ /* Create credential cache for kadmin */
+ if (!cache_name[0])
+ (void) sprintf(cache_name, "FILE:/tmp/tkt_adm_%d", getpid());
+
+ if ((retval = krb5_cc_resolve(context, cache_name, &cache))) {
+ fprintf(stderr, "Unable to Resolve Cache: %s!\n", cache_name);
+ }
+
+ if ((retval = krb5_cc_initialize(context, cache, client))) {
+ fprintf(stderr, "Error initializing cache: %s!\n", cache_name);
+ exit(1);
+ }
+
+/*
+ * Verify User by Obtaining Initial Credentials prior to Initial Link
+ */
+
+ if ((retval = get_first_ticket(context, cache, client, &my_creds))) {
+ (void) krb5_cc_destroy(context, cache);
+ exit(1);
+ }
+ /* my_creds has the necessary credentials for further processing:
+ Destroy credential cache for security reasons */
+ (void) krb5_cc_destroy(context, cache);
+
+ requested_realm = (krb5_data *) &client->realm;
+
+
+ /* Initiate Link to Server */
+ if ((retval = adm5_init_link(context, requested_realm, port,
+ &local_socket))) {
+ (void) krb5_cc_destroy(context, cache);
+ exit(1);
+ }
+
+#ifdef unicos61
+#define SIZEOF_INADDR SIZEOF_in_addr
+#else
+#define SIZEOF_INADDR sizeof(struct in_addr)
+#endif
+
+/* V4 kpasswd Protocol Hack
+ * Necessary for ALL kadmind clients
+ */
+ {
+ int msg_length = 0;
+
+ retval = krb5_net_write(context, local_socket, (char *) &msg_length + 2, 2);
+ if (retval < 0) {
+ fprintf(stderr, "krb5_net_write failure!\n");
+ (void) krb5_cc_destroy(context, cache);
+ exit(1);
+ }
+ }
+
+ local_addr.addrtype = ADDRTYPE_INET;
+ local_addr.length = SIZEOF_INADDR ;
+ local_addr.contents = (krb5_octet *) &local_sin.sin_addr;
+
+ foreign_addr.addrtype = ADDRTYPE_INET;
+ foreign_addr.length = SIZEOF_INADDR ;
+ foreign_addr.contents = (krb5_octet *) &remote_sin.sin_addr;
+
+ krb5_auth_con_init(context, &new_auth_context);
+ krb5_auth_con_setflags(context, new_auth_context,
+ KRB5_AUTH_CONTEXT_RET_SEQUENCE);
+
+ krb5_auth_con_setaddrs(context, new_auth_context,
+ &local_addr, &foreign_addr);
+
+ /* call Kerberos library routine to obtain an authenticator,
+ pass it over the socket to the server, and obtain mutual
+ authentication. */
+
+ inbuf.data = ADM5_ADM_VERSION;
+ inbuf.length = strlen(ADM5_ADM_VERSION);
+
+ if ((retval = krb5_sendauth(context, &new_auth_context,
+ (krb5_pointer) &local_socket,
+ ADM_CPW_VERSION,
+ my_creds.client,
+ my_creds.server,
+ AP_OPTS_MUTUAL_REQUIRED,
+ &inbuf,
+ &my_creds,
+ 0,
+ &err_ret,
+ &rep_ret,
+ NULL))) {
+ fprintf(stderr, "Error while performing sendauth: %s!\n",
+ error_message(retval));
+ exit(1);
+ }
+
+ /* Read back what the server has to say ... */
+ if (retval = krb5_read_message(context, &local_socket, &inbuf)){
+ fprintf(stderr, " Read Message Error: %s!\n",
+ error_message(retval));
+ exit(1);
+ }
+
+ if ((inbuf.length != 2) || (inbuf.data[0] != KADMIND) ||
+ (inbuf.data[1] != KADMSAG)){
+ fprintf(stderr, " Invalid ack from admin server.!\n");
+ exit(1);
+ }
+ free(inbuf.data);
+
+ if ((inbuf.data = (char *) calloc(1, 2)) == (char *) 0) {
+ fprintf(stderr, "No memory for command!\n");
+ exit(1);
+ }
+
+ inbuf.data[0] = KADMIN;
+ inbuf.data[1] = 0xff;
+ inbuf.length = 2;
+
+ if ((retval = krb5_mk_priv(context, new_auth_context, &inbuf,
+ &msg_data, &replaydata))) {
+ fprintf(stderr, "Error during First Message Encoding: %s!\n",
+ error_message(retval));
+ free(inbuf.data);
+ exit(1);
+ }
+ free(inbuf.data);
+
+ /* write private message to server */
+ if (krb5_write_message(context, &local_socket, &msg_data)){
+ fprintf(stderr, "Write Error During First Message Transmission!\n");
+ exit(1);
+ }
+ free(msg_data.data);
+
+ for ( ; ; ) {
+ /* Ok Now let's get the private message */
+ if (retval = krb5_read_message(context, &local_socket, &inbuf)){
+ fprintf(stderr, "Read Error During First Reply: %s!\n",
+ error_message(retval));
+ exit(1);
+ }
+
+ if ((retval = krb5_rd_priv(context, new_auth_context, &inbuf,
+ &msg_data, &replaydata))) {
+ fprintf(stderr, "Error during First Read Decoding: %s!\n",
+ error_message(retval));
+ exit(1);
+ }
+ free(inbuf.data);
+
+ valid = 0;
+ princ_name[0] = '\0';
+repeat:
+ printf("\n\nCommand (add, cpw, del, inq, mod, addrnd, cpwrnd, addv4, cpwv4, q): ");
+ fgets(buffer, sizeof(buffer), stdin);
+ buffer[strlen(buffer) -1] = '\0';
+ sscanf(buffer,"%s %s", command_type, princ_name);
+ for (i = 0; command_type[i] != '\0'; i++)
+ if (isupper(command_type[i]))
+ command_type[i] = tolower(command_type[i]);
+
+ if (!strcmp(command_type, "add")) {
+ valid++;
+ oper_type = ADDOPER;
+ if (retval = kadm_add_user(context, new_auth_context, &my_creds,
+ &local_socket, oper_type, princ_name))
+ break;
+ }
+ if (!strcmp(command_type, "cpw")) {
+ valid++;
+ oper_type = CHGOPER;
+ if (retval = kadm_cpw_user(context, new_auth_context, &my_creds,
+ &local_socket, oper_type, princ_name))
+ break;
+ }
+ if (!strcmp(command_type, "addrnd")) {
+ valid++;
+ if (retval = kadm_add_user_rnd(context, new_auth_context, &my_creds,
+ &local_socket, princ_name))
+ break;
+ }
+ if (!strcmp(command_type, "cpwrnd")) {
+ valid++;
+ if (retval = kadm_cpw_user_rnd(context, new_auth_context, &my_creds,
+ &local_socket, princ_name))
+ break;
+ }
+ if (!strcmp(command_type, "del")) {
+ valid++;
+ if (retval = kadm_del_user(context, new_auth_context, &my_creds,
+ &local_socket, princ_name))
+ break;
+ }
+ if (!strcmp(command_type, "inq")) {
+ valid++;
+ if (retval = kadm_inq_user(context, new_auth_context, &my_creds,
+ &local_socket, princ_name))
+ break;
+ }
+ if (!strcmp(command_type, "mod")) {
+ valid++;
+ if (retval = kadm_mod_user(context, new_auth_context, &my_creds,
+ &local_socket, princ_name))
+ break;
+ }
+ if (!strcmp(command_type, "addv4")) {
+ valid++;
+ oper_type = AD4OPER;
+ if (retval = kadm_add_user(context, new_auth_context, &my_creds,
+ &local_socket, oper_type, princ_name))
+ break;
+ }
+ if (!strcmp(command_type, "cpwv4")) {
+ valid++;
+ oper_type = CH4OPER;
+ if (retval = kadm_cpw_user(context, new_auth_context, &my_creds,
+ &local_socket, oper_type, princ_name))
+ break;
+ }
+ if (!strcmp(command_type, "q")) {
+ valid++;
+ retval = kadm_done(context, new_auth_context, &my_creds,
+ &local_socket);
+ break;
+ }
+
+ if (!valid) {
+ fprintf(stderr, "Invalid Input - Retry\n");
+ goto repeat;
+ }
+ }
+
+ if (retval) {
+ exit(1);
+ }
+
+ /* Ok Now let's get the final private message */
+ if (retval = krb5_read_message(context, &local_socket, &inbuf)){
+ fprintf(stderr, "Read Error During Final Reply: %s!\n",
+ error_message(retval));
+ exit(1);
+ }
+
+ if ((retval = krb5_rd_priv(context, new_auth_context, &inbuf,
+ &msg_data, &replaydata))) {
+ fprintf(stderr, "Error during Final Read Decoding :%s!\n",
+ error_message(retval));
+ free(inbuf.data);
+ exit(1);
+ }
+ free(inbuf.data);
+
+ decode_kadmind_reply(msg_data, &rd_priv_resp);
+ free(msg_data.data);
+
+ if (!((rd_priv_resp.appl_code == KADMIN) &&
+ (rd_priv_resp.retn_code == KADMGOOD))) {
+ if (rd_priv_resp.message)
+ fprintf(stderr, "%s\n", rd_priv_resp.message);
+ else
+ fprintf(stderr, "Generic Error During kadmin Termination!\n");
+ retval = 1;
+ } else {
+ fprintf(stderr, "\nHave a Good Day.\n\n");
+ }
+
+ if (rd_priv_resp.message)
+ free(rd_priv_resp.message);
+
+
+ exit(retval);
+}
+
+static krb5_error_code
+get_first_ticket(context, cache, client, my_creds)
+ krb5_context context;
+ krb5_ccache cache;
+ krb5_principal client;
+ krb5_creds * my_creds;
+{
+ char prompt[255]; /* for the password prompt */
+
+ krb5_address **my_addresses;
+
+ char *client_name;
+ krb5_error_code retval;
+ char *password;
+ int pwsize;
+ int i;
+
+ if ((retval = krb5_unparse_name(context, client, &client_name))) {
+ fprintf(stderr, "Unable to Unparse Client Name!\n");
+ return(1);
+ }
+
+ if ((retval = krb5_os_localaddr(&my_addresses))) {
+ fprintf(stderr, "Unable to Get Principals Address!\n");
+ return(1);
+ }
+
+ memset((char *) my_creds, 0, sizeof(krb5_creds));
+
+ my_creds->client = client;
+
+ if ((retval = krb5_build_principal_ext(context, &my_creds->server,
+ client->realm.length,
+ client->realm.data,
+ strlen(CPWNAME),
+ CPWNAME, /* kadmin */
+ client->realm.length,
+ client->realm.data,
+ /* instance is <realm> */
+ 0))) {
+ fprintf(stderr, "Error %s while building client name!\n",
+ error_message(retval));
+ krb5_free_addresses(context, my_addresses);
+ return(1);
+ }
+
+ (void) sprintf(prompt,"Password for %s: ", (char *) client_name);
+
+ if ((password = (char *) calloc (1, 255)) == NULL) {
+ fprintf(stderr, "No Memory for Retrieving Admin Password!\n");
+ return(1);
+ }
+
+ pwsize = 255;
+ if ((retval = krb5_read_password(context,
+ prompt,
+ 0,
+ password,
+ &pwsize) || pwsize == 0)) {
+ fprintf(stderr, "Error while reading password for '%s'!\n",
+ client_name);
+ free(password);
+ krb5_free_addresses(context, my_addresses);
+ return(1);
+ }
+
+ /* Build Request for Initial Credentials */
+ retval = krb5_get_in_tkt_with_password(context, 0, /* options */
+ my_addresses,
+ NULL, /* Default encryption list */
+ NULL, /* Default preauth list */
+ password, cache, my_creds, 0);
+
+ /* Do NOT Forget to zap password */
+ memset((char *) password, 0, pwsize);
+ free(password);
+ krb5_free_addresses(context, my_addresses);
+
+ if (retval) {
+ fprintf(stderr, "\nUnable to Get Initial Credentials: %s!\n",
+ error_message(retval));
+ return(1);
+ }
+
+ return(0);
+}
+
+krb5_error_code
+adm5_init_link(context, realm_of_server, port, local_socket)
+ krb5_context context;
+ krb5_data *realm_of_server;
+ int port;
+ int * local_socket;
+{
+ struct servent *service_process; /* service we will talk to */
+ struct hostent *remote_host; /* host we will talk to */
+ char **hostlist;
+ int namelen;
+ int i;
+
+ krb5_error_code retval;
+
+ /* clear out the structure first */
+ (void) memset((char *)&remote_sin, 0, sizeof(remote_sin));
+
+ if (port != 0) {
+ remote_sin.sin_port = port;
+ } else {
+ if ((service_process = getservbyname(CPW_SNAME, "tcp")) == NULL) {
+ fprintf(stderr, "Unable to find Service (%s) Check services file!\n",
+ CPW_SNAME);
+ return(1);
+ }
+
+ /* Copy the Port Number */
+ remote_sin.sin_port = service_process->s_port;
+ }
+
+ hostlist = 0;
+
+ /* Identify all Hosts Associated with this Realm */
+ if ((retval = krb5_get_krbhst (context, realm_of_server, &hostlist))) {
+ fprintf(stderr, "krb5_get_krbhst: Unable to Determine Server Name!\n");
+ return(retval);
+ }
+
+ if (hostlist[0] == 0) {
+ fprintf(stderr, "No hosts found!\n");
+ return KRB5_REALM_UNKNOWN;
+ }
+
+ for (i=0; hostlist[i]; i++) {
+ remote_host = gethostbyname(hostlist[i]);
+ if (remote_host != 0) {
+
+ /* set up the address of the foreign socket for connect() */
+ remote_sin.sin_family = remote_host->h_addrtype;
+ (void) memcpy((char *) &remote_sin.sin_addr,
+ (char *) remote_host->h_addr,
+ sizeof(remote_host->h_addr));
+ break; /* Only Need one */
+ }
+ }
+
+ krb5_free_krbhst(context, hostlist);
+
+ /* open a TCP socket */
+ *local_socket = socket(PF_INET, SOCK_STREAM, 0);
+ if (*local_socket < 0) {
+ retval = errno;
+ fprintf(stderr, "Cannot Open Socket!\n");
+ return retval;
+ }
+ /* connect to the server */
+ if (connect(*local_socket, &remote_sin, sizeof(remote_sin)) < 0) {
+ retval = errno;
+ fprintf(stderr, "Cannot Connect to Socket!\n");
+ close(*local_socket);
+ return retval;
+ }
+
+ /* find out who I am, now that we are connected and therefore bound */
+ namelen = sizeof(local_sin);
+ if (getsockname(*local_socket,
+ (struct sockaddr *) &local_sin, &namelen) < 0) {
+ retval = errno;
+ fprintf(stderr, "Cannot Perform getsockname!\n");
+ close(*local_socket);
+ return retval;
+ }
+ return 0;
+}
+
+static void
+get_def_princ(context, client)
+ krb5_context context;
+ krb5_principal *client;
+{
+ krb5_ccache cache = NULL;
+ struct passwd *pw;
+ int retval;
+ char client_name[755];
+ krb5_flags cc_flags;
+
+ /* Identify Default Credentials Cache */
+ if (retval = krb5_cc_default(context, &cache)) {
+ fprintf(stderr, "Error while getting default ccache!\n");
+ exit(1);
+ }
+
+ /*
+ * Attempt to Modify Credentials Cache
+ * retval == 0 ==> ccache Exists - Use It
+ * retval == ENOENT ==> No Entries, but ccache Exists
+ * retval != 0 ==> Assume ccache does NOT Exist
+ */
+ cc_flags = 0;
+ if (retval = krb5_cc_set_flags(context, cache, cc_flags)) {
+ /* Search passwd file for client */
+ pw = getpwuid((int) getuid());
+ if (pw) {
+ (void) strcpy(client_name, pw->pw_name);
+ if (!strncmp("root", client_name, strlen(client_name))) {
+ fprintf(stderr,
+ "root is not a valid Adimnistrator\n!\n");
+ usage();
+ }
+ } else {
+ fprintf(stderr,
+ "Unable to Identify Principal from Password File!\n");
+ retval = 1;
+ usage();
+ }
+
+ /* Use this to get default_realm and format client_name */
+ if ((retval = krb5_parse_name(context, client_name, client))) {
+ fprintf(stderr, "Unable to Parse Client Name!\n");
+ usage();
+ }
+ } else {
+ /* Read Client from Cache */
+ if (retval = krb5_cc_get_principal(context, cache, client)) {
+ fprintf(stderr,
+ "Unable to Read Principal Credentials File!\n");
+ exit(1);
+ }
+
+ if (!strncmp("root", (*client)->data[0].data,
+ (*client)->data[0].length)) {
+ fprintf(stderr, "root is not a valid Administrator\n!\n");
+ usage();
+ }
+
+ (void) krb5_cc_close(context, cache);
+ }
+}
+
+usage()
+{
+ fprintf(stderr, "Usage: ");
+ fprintf(stderr, "kadmin [-n] [-p port] [Administrator name]\n\n");
+ fprintf(stderr, " If an Administrator name is not supplied, kadmin ");
+ fprintf(stderr, "will first\n attempt to locate the name from ");
+ fprintf(stderr, "the default ticket file, then\n by using the ");
+ fprintf(stderr, "username from the 'passwd' file.\n\n");
+ fprintf(stderr, " For Cross Realm Obtain a ticket for 'Administrator ");
+ fprintf(stderr, "name' in the\n Destination realm or ");
+ fprintf(stderr, "specify the Destination Realm\n as part of the ");
+ fprintf(stderr, "Administrator name option.\n\n");
+ fprintf(stderr, " Note: If the Administrator Name is not ");
+ fprintf(stderr, "supplied, then the \n");
+ fprintf(stderr, " '/admin' instance will be appended to the ");
+ fprintf(stderr, "default name unless\n");
+ fprintf(stderr, " the -n option is used.\n\n");
+ exit(0);
+}
+
+void decode_kadmind_reply(data, response)
+ krb5_data data;
+ kadmin_requests *response;
+{
+ response->appl_code = data.data[0];
+ response->oper_code = data.data[1];
+ response->retn_code = data.data[2];
+ if (data.length > 3 && data.data[3]) {
+ response->message = (char *)malloc(data.length - 2);
+ if (response->message) {
+ memcpy(response->message, data.data + 3, data.length - 3);
+ response->message[data.length - 3] = 0;
+ }
+ } else
+ response->message = NULL;
+
+ return;
+}
+
+int print_status_message(response, success_msg)
+ kadmin_requests *response;
+ char *success_msg;
+{
+ int retval = 1;
+
+ if (response->appl_code == KADMIN) {
+ if (response->retn_code == KADMGOOD) {
+ fprintf(stderr, "%s\n", success_msg);
+ retval = 0;
+ } else if (response->retn_code == KADMBAD)
+ fprintf(stderr, "%s\n", response->message);
+ else
+ fprintf(stderr, "ERROR: unknown return code from server.\n");
+ } else
+ fprintf(stderr, "ERROR: unknown application code from server.\n");
+
+ if (response->message)
+ free(response->message);
+
+ return retval;
+}
--- /dev/null
+/*
+ * kadmin/client/kadmin_add.c
+ *
+ * Copyright 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ *
+ */
+
+/*
+ * Sandia National Laboratories also makes no representations about the
+ * suitability of the modifications, or additions to this software for
+ * any purpose. It is provided "as is" without express or implied warranty.
+ */
+
+
+/*
+ * kadmin_add
+ * Perform Remote Kerberos Administrative Functions
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <string.h>
+#include "com_err.h"
+
+#include <sys/param.h>
+
+#include "k5-int.h"
+#include "adm_defs.h"
+
+void decode_kadmind_reply();
+int print_status_message();
+
+krb5_error_code
+kadm_add_user(context, auth_context, my_creds, local_socket,
+ oper_type, principal)
+ krb5_context context;
+ krb5_auth_context * auth_context;
+ krb5_creds * my_creds;
+ int * local_socket;
+ int oper_type;
+ char * principal;
+{
+ krb5_data msg_data, inbuf;
+ kadmin_requests rd_priv_resp;
+ char username[255];
+ char *password;
+ int pwsize;
+ int count;
+ krb5_replay_data replaydata;
+ krb5_error_code retval; /* return code */
+
+ if ((inbuf.data = (char *) calloc(1, 3 + sizeof(username))) == (char *) 0) {
+ fprintf(stderr, "No memory for command!\n");
+ return(1);
+ }
+
+ inbuf.data[0] = KADMIN;
+ inbuf.data[1] = oper_type;
+ inbuf.data[2] = SENDDATA2;
+
+ if (principal && principal[0] != '\0')
+ strcpy(username, principal);
+ else {
+ count = 0;
+ do {
+ fprintf(stdout, "\nName of Principal to be Added: ");
+ fgets(username, sizeof(username), stdin);
+ if (username[0] == '\n')
+ fprintf(stderr, "Invalid Principal name!\n");
+ count++;
+ } while (username[0] == '\n' && count < 3);
+
+ if (username[0] == '\n') {
+ fprintf(stderr, "Aborting!!\n\n");
+ return(1);
+ }
+
+ username[strlen(username) -1] = '\0';
+ }
+
+ (void) memcpy( inbuf.data + 3, username, strlen(username));
+ inbuf.length = strlen(username) + 3;
+
+ if ((retval = krb5_mk_priv(context, auth_context, &inbuf,
+ &msg_data, &replaydata))) {
+ fprintf(stderr, "Error during Second Message Encoding: %s!\n",
+ error_message(retval));
+ free(inbuf.data);
+ return(1);
+ }
+ free(inbuf.data);
+
+ /* write private message to server */
+ if (krb5_write_message(context, local_socket, &msg_data)){
+ fprintf(stderr, "Write Error During Second Message Transmission!\n");
+ return(1);
+ }
+
+ free(msg_data.data);
+
+ if (retval = krb5_read_message(context, local_socket, &inbuf)){
+ fprintf(stderr, "Read Error During Second Reply: %s!\n",
+ error_message(retval));
+ return(1);
+ }
+
+ if (retval = krb5_rd_priv(context, auth_context, &inbuf,
+ &msg_data, &replaydata)) {
+ fprintf(stderr, "Error during Second Read Decoding :%s!\n",
+ error_message(retval));
+ free(inbuf.data);
+ return(1);
+ }
+ free(inbuf.data);
+
+ if (msg_data.data[2] == KADMBAD) {
+ decode_kadmind_reply(msg_data, &rd_priv_resp);
+
+ if (rd_priv_resp.message) {
+ fprintf(stderr, "%s\n\n", rd_priv_resp.message);
+ free(rd_priv_resp.message);
+ } else
+ fprintf(stderr, "Generic error from server.\n\n");
+ return(0);
+ }
+
+#ifdef MACH_PASS
+ pwsize = msg_data.length;
+ if ((password = (char *) calloc (1, pwsize)) == (char *) 0) {
+ fprintf(stderr, "No Memory for allocation of password!\n");
+ retval = 1;
+ free(msg_data.data);
+ return(1);
+ }
+
+ memcpy(password, msg_data.data, pwsize);
+ memset(msg_data.data, 0, pwsize);
+ password[pwsize] = '\0';
+ fprintf(stdout, "\nPassword for \"%s\" is \"%s\"\n", username, password);
+ memset(password, 0, pwsize);
+ free(password);
+ fprintf(stdout, "\nThis password can only be used to execute kpasswd\n\n");
+
+ free(msg_data.data);
+
+ if ((inbuf.data = (char *) calloc(1, 2)) == (char *) 0) {
+ fprintf(stderr, "No memory for command!\n");
+ return(1);
+ }
+
+ inbuf.data[0] = KADMIN;
+ inbuf.data[1] = KADMGOOD;
+ inbuf.length = 2;
+
+#else
+
+ if ((password = (char *) calloc (1, ADM_MAX_PW_LENGTH+1)) == (char *) 0) {
+ fprintf(stderr, "No Memory for allocation of password!\n");
+ return(1);
+ }
+
+ pwsize = ADM_MAX_PW_LENGTH+1;
+
+ putchar('\n');
+ if (retval = krb5_read_password(context,
+ DEFAULT_PWD_STRING1,
+ DEFAULT_PWD_STRING2,
+ password,
+ &pwsize)) {
+ fprintf(stderr, "Error while reading new password for %s: %s!\n",
+ username, error_message(retval));
+ (void) memset((char *) password, 0, ADM_MAX_PW_LENGTH+1);
+ free(password);
+ return(1);
+ }
+
+ if ((inbuf.data = (char *) calloc(1, strlen(password) + 1)) == (char *) 0) {
+ fprintf(stderr, "No Memory for allocation of buffer!\n");
+ (void) memset((char *) password, 0, ADM_MAX_PW_LENGTH+1);
+ free(password);
+ return(1);
+ }
+
+ inbuf.length = strlen(password);
+ (void) memcpy(inbuf.data, password, strlen(password));
+ free(password);
+
+#endif /* MACH_PASS */
+
+ if ((retval = krb5_mk_priv(context, auth_context, &inbuf,
+ &msg_data, &replaydata))) {
+ fprintf(stderr, "Error during Second Message Encoding: %s!\n",
+ error_message(retval));
+ free(inbuf.data);
+ return(1);
+ }
+ free(inbuf.data);
+
+ /* write private message to server */
+ if (krb5_write_message(context, local_socket, &msg_data)){
+ fprintf(stderr, "Write Error During Second Message Transmission!\n");
+ return(1);
+ }
+ free(msg_data.data);
+
+ /* Ok Now let's get the final private message */
+ if (retval = krb5_read_message(context, local_socket, &inbuf)){
+ fprintf(stderr, "Read Error During Final Reply: %s!\n",
+ error_message(retval));
+ retval = 1;
+ }
+
+ if ((retval = krb5_rd_priv(context, auth_context, &inbuf,
+ &msg_data, &replaydata))) {
+ fprintf(stderr, "Error during Final Read Decoding :%s!\n",
+ error_message(retval));
+ free(inbuf.data);
+ return(1);
+ }
+ free(inbuf.data);
+
+ decode_kadmind_reply(msg_data, &rd_priv_resp);
+
+ free(msg_data.data);
+
+ retval = print_status_message(&rd_priv_resp,
+ "Database Addition Successful.");
+
+ return(retval);
+}
--- /dev/null
+/*
+ * kadmin/client/kadmin_adr.c
+ *
+ * Copyright 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ *
+ */
+
+/*
+ * Sandia National Laboratories also makes no representations about the
+ * suitability of the modifications, or additions to this software for
+ * any purpose. It is provided "as is" without express or implied warranty.
+ */
+
+
+/*
+ * kadmin_adr
+ * Perform Remote Kerberos Administrative Functions
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <string.h>
+#include <com_err.h>
+
+#include <sys/param.h>
+
+#include <krb5.h>
+#include "adm_defs.h"
+
+void decode_kadmind_reply();
+int print_status_message();
+
+krb5_error_code
+kadm_add_user_rnd(context, auth_context, my_creds,
+ local_socket, seqno, principal)
+ krb5_context context;
+ krb5_auth_context *auth_context;
+ int *local_socket;
+ krb5_int32 *seqno;
+ char *principal;
+{
+ krb5_data msg_data, inbuf;
+ kadmin_requests rd_priv_resp;
+ char username[755];
+ int count;
+ krb5_replay_data replaydata;
+ krb5_error_code retval; /* return code */
+
+ if ((inbuf.data = (char *) calloc(1, 3 + sizeof(username))) == (char *) 0) {
+ fprintf(stderr, "No memory for command!\n");
+ return(1);
+ }
+
+ inbuf.data[0] = KADMIN;
+ inbuf.data[1] = ADROPER;
+ inbuf.data[2] = SENDDATA2;
+
+ if (principal && principal[0] != '\0')
+ strcpy(username, principal);
+ else {
+ count = 0;
+ do {
+ fprintf(stdout, "\nName of Principal to be Added: ");
+ fgets(username, sizeof(username), stdin);
+ if (username[0] == '\n')
+ fprintf(stderr, "Invalid Principal name!\n");
+ count++;
+ }
+ while (username[0] == '\n' && count < 3);
+
+ if (username[0] == '\n') {
+ fprintf(stderr, "Aborting!!\n\n");
+ return(1);
+ }
+ username[strlen(username) -1] = '\0';
+ }
+
+
+ (void) memcpy( inbuf.data + 3, username, strlen(username));
+ inbuf.length = strlen(username) + 3;
+
+ if ((retval = krb5_mk_priv(context, auth_context, &inbuf,
+ &msg_data, &replaydata))) {
+ fprintf(stderr, "Error during Second Message Encoding: %s!\n",
+ error_message(retval));
+ free(inbuf.data);
+ return(1);
+ }
+ free(inbuf.data);
+
+ /* write private message to server */
+ if (krb5_write_message(context, local_socket, &msg_data)){
+ fprintf(stderr, "Write Error During Second Message Transmission!\n");
+ return(1);
+ }
+
+ free(msg_data.data);
+
+ /* Ok Now let's get the final private message */
+ if (retval = krb5_read_message(context, local_socket, &inbuf)){
+ fprintf(stderr, "Read Error During Final Reply: %s!\n",
+ error_message(retval));
+ retval = 1;
+ }
+
+ if ((retval = krb5_rd_priv(context, auth_context, &inbuf,
+ &msg_data, &replaydata))) {
+ fprintf(stderr, "Error during Final Read Decoding :%s!\n",
+ error_message(retval));
+ free(inbuf.data);
+ return(1);
+ }
+
+ decode_kadmind_reply(msg_data, &rd_priv_resp);
+
+ free(inbuf.data);
+ free(msg_data.data);
+
+ retval = print_status_message(&rd_priv_resp,
+ "Database Addition Successful.");
+
+ return(retval);
+}
--- /dev/null
+/*
+ * kadmin/client/kadmin_cpr.c
+ *
+ * Copyright 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ *
+ */
+
+/*
+ * Sandia National Laboratories also makes no representations about the
+ * suitability of the modifications, or additions to this software for
+ * any purpose. It is provided "as is" without express or implied warranty.
+ */
+
+
+/*
+ * kadmin_cpr
+ * Perform Remote Kerberos Administrative Functions
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <signal.h>
+#include <string.h>
+#include <com_err.h>
+
+#include <sys/param.h>
+
+#include <krb5.h>
+#include "adm_defs.h"
+
+void decode_kadmind_reply();
+int print_status_message();
+
+krb5_error_code
+kadm_cpw_user_rnd(context, auth_context, my_creds,
+ local_socket, seqno, principal)
+ krb5_context context;
+ krb5_auth_context *auth_context;
+ int *local_socket;
+ krb5_int32 *seqno;
+ char *principal;
+{
+ krb5_data msg_data, inbuf;
+ kadmin_requests rd_priv_resp;
+ char username[755];
+ int count;
+ krb5_replay_data replaydata;
+ krb5_error_code retval; /* return code */
+
+ if ((inbuf.data = (char *) calloc(1, 3 + sizeof(username))) == (char *) 0) { fprintf(stderr, "No memory for command!\n");
+ exit(1);
+ }
+
+ inbuf.data[0] = KADMIN;
+ inbuf.data[1] = CHROPER;
+ inbuf.data[2] = SENDDATA2;
+
+ if (principal && principal[0] != '\0')
+ strcpy(username, principal);
+ else {
+ count = 0;
+ do {
+ fprintf(stdout,
+ "\nName of Principal Whose Password is to Change: ");
+ fgets(username, sizeof(username), stdin);
+ if (username[0] == '\n')
+ fprintf(stderr, "Invalid Principal name!\n");
+ count++;
+ }
+ while (username[0] == '\n' && count < 3);
+
+ if (username[0] == '\n') {
+ fprintf(stderr, "Aborting!!\n\n");
+ return(1);
+ }
+ username[strlen(username) -1] = '\0';
+ }
+
+ (void) memcpy( inbuf.data + 3, username, strlen(username));
+ inbuf.length = strlen(username) + 3;
+
+ /* Transmit Principal Name */
+ if ((retval = krb5_mk_priv(context, auth_context, &inbuf,
+ &msg_data, &replaydata))) {
+ fprintf(stderr, "Error during Second Message Encoding: %s!\n",
+ error_message(retval));
+ free(inbuf.data);
+ return(1);
+ }
+ free(inbuf.data);
+
+ /* write private message to server */
+ if (krb5_write_message(context, local_socket, &msg_data)){
+ fprintf(stderr, "Write Error During Second Message Transmission!\n");
+ return(1);
+ }
+ free(msg_data.data);
+
+ /* Ok Now let's get the final private message */
+ if (retval = krb5_read_message(context, local_socket, &inbuf)){
+ fprintf(stderr, "Read Error During Final Reply: %s!\n",
+ error_message(retval));
+ retval = 1;
+ }
+
+ if ((retval = krb5_rd_priv(context, auth_context, &inbuf,
+ &msg_data, &replaydata))) {
+ fprintf(stderr, "Error during Final Read Decoding :%s!\n",
+ error_message(retval));
+ free(inbuf.data);
+ return(1);
+ }
+ free(inbuf.data);
+
+ decode_kadmind_reply(msg_data, &rd_priv_resp);
+
+ free(inbuf.data);
+ free(msg_data.data);
+
+ print_status_message(&rd_priv_resp,
+ "Password Modification Successful.");
+
+ return(0);
+}
+
+
--- /dev/null
+/*
+ * kadmin/client/kadmin_cpw.c
+ *
+ * Copyright 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ *
+ */
+
+/*
+ * Sandia National Laboratories also makes no representations about the
+ * suitability of the modifications, or additions to this software for
+ * any purpose. It is provided "as is" without express or implied warranty.
+ */
+
+
+/*
+ * kadmin_cpw
+ * Perform Remote Kerberos Administrative Functions
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <signal.h>
+#include <string.h>
+#include <com_err.h>
+
+#include <sys/param.h>
+
+#include <k5-int.h>
+#include "adm_defs.h"
+
+void decode_kadmind_reply();
+int print_status_message();
+
+krb5_error_code
+kadm_cpw_user(context, auth_context, my_creds,
+ local_socket, oper_type, principal)
+ krb5_context context;
+ krb5_auth_context *auth_context;
+ int *local_socket;
+ int oper_type;
+ char *principal;
+{
+ krb5_data msg_data, inbuf;
+ kadmin_requests rd_priv_resp;
+ char username[255];
+ char *password;
+ int pwsize;
+ int count;
+ krb5_replay_data replaydata;
+ krb5_error_code retval; /* return code */
+
+ if ((inbuf.data = (char *) calloc(1, 3 + sizeof(username))) == (char *) 0) { fprintf(stderr, "No memory for command!\n");
+ exit(1);
+ }
+
+ inbuf.data[0] = KADMIN;
+ inbuf.data[1] = oper_type;
+ inbuf.data[2] = SENDDATA2;
+
+ if (principal && principal[0] != '\0')
+ strcpy(username, principal);
+ else {
+ count = 0;
+ do {
+ fprintf(stdout,
+ "\nName of Principal Whose Password is to Change: ");
+ fgets(username, sizeof(username), stdin);
+ if (username[0] == '\n')
+ fprintf(stderr, "Invalid Principal name!\n");
+ count++;
+ }
+ while (username[0] == '\n' && count < 3);
+
+ if (username[0] == '\n') {
+ fprintf(stderr, "Aborting!!\n\n");
+ return(1);
+ }
+
+ username[strlen(username) -1] = '\0';
+ }
+
+ (void) memcpy( inbuf.data + 3, username, strlen(username));
+ inbuf.length = strlen(username) + 3;
+
+ /* Transmit Principal Name */
+ if ((retval = krb5_mk_priv(context, auth_context, &inbuf,
+ &msg_data, &replaydata))) {
+ fprintf(stderr, "Error during Second Message Encoding: %s!\n",
+ error_message(retval));
+ free(inbuf.data);
+ return(1);
+ }
+ free(inbuf.data);
+
+ /* write private message to server */
+ if (krb5_write_message(context, local_socket, &msg_data)){
+ free(msg_data.data);
+ fprintf(stderr, "Write Error During Second Message Transmission!\n");
+ return(1);
+ }
+ free(msg_data.data);
+
+ if (retval = krb5_read_message(context, local_socket, &inbuf)){
+ fprintf(stderr, "Read Error During Second Reply: %s!\n",
+ error_message(retval));
+ return(1);
+ }
+
+ if ((retval = krb5_rd_priv(context, auth_context, &inbuf,
+ &msg_data, &replaydata))) {
+ fprintf(stderr, "Error during Second Read Decoding :%s!\n",
+ error_message(retval));
+ free(inbuf.data);
+ return(1);
+ }
+ free(inbuf.data);
+
+ if (msg_data.data[2] == KADMBAD) {
+ decode_kadmind_reply(msg_data, &rd_priv_resp);
+
+ if (rd_priv_resp.message) {
+ fprintf(stderr, "%s\n\n", rd_priv_resp.message);
+ free(rd_priv_resp.message);
+ } else
+ fprintf(stderr, "Generic error from server.\n\n");
+ memset(msg_data.data, 0, msg_data.length);
+ free(msg_data.data);
+ return(0);
+ }
+
+ if ((oper_type == CHGOPER && msg_data.data[3] == KRB5_KDB_SALTTYPE_V4) ||
+ (oper_type == CH4OPER && msg_data.data[3] == KRB5_KDB_SALTTYPE_NORMAL))
+ fprintf(stderr, "WARNING: Changing Principal Salt type to %s!\n",
+ (msg_data.data[3] == KRB5_KDB_SALTTYPE_V4) ?
+ "Version 5 Normal" : "Version 4");
+
+#ifdef MACH_PASS /* Machine-generated passwords */
+ pwsize = msg_data.length;
+ if ((password = (char *) calloc (1, pwsize)) == (char *) 0) {
+ fprintf(stderr, "No Memory for allocation of password!\n");
+ memset(msg_data.data, 0, msg_data.length);
+ free(msg_data.data);
+ return(1);
+ }
+
+ memcpy(password, msg_data.data, pwsize);
+ memset(msg_data.data, 0, pwsize);
+ free(msg_data.data);
+ password[pwsize] = '\0';
+ fprintf(stdout, "\nPassword for \"%s\" is \"%s\"\n", username, password);
+ memset(password, 0, pwsize);
+ free(password);
+ fprintf(stdout, "\nThis password can only be used to execute kpasswd\n\n");
+
+ if ((inbuf.data = (char *) calloc(1, 2)) == (char *) 0) {
+ fprintf(stderr, "No memory for command!\n");
+ return(1);
+ }
+
+ inbuf.data[0] = KADMIN;
+ inbuf.data[1] = KADMGOOD;
+ inbuf.length = 2;
+
+#else
+
+ if ((password = (char *) calloc (1, ADM_MAX_PW_LENGTH+1)) == (char *) 0) {
+ fprintf(stderr, "No Memory for allocation of password!\n");
+ return(1);
+ }
+
+ pwsize = ADM_MAX_PW_LENGTH+1;
+
+ putchar('\n');
+ if ((retval = krb5_read_password(context,
+ DEFAULT_PWD_STRING1,
+ DEFAULT_PWD_STRING2,
+ password,
+ &pwsize))) {
+ fprintf(stderr, "Error while reading new password for %s: %s!\n",
+ username, error_message(retval));
+ (void) memset((char *) password, 0, ADM_MAX_PW_LENGTH+1);
+ free(password);
+ return(1);
+ }
+
+ if ((inbuf.data = (char *) calloc (1, strlen(password) + 1)) ==
+ (char *) 0) {
+ fprintf(stderr, "No Memory for allocation of buffer!\n");
+ (void) memset((char *) password, 0, ADM_MAX_PW_LENGTH+1);
+ free(password);
+ return(1); /* No Memory */
+ }
+
+ inbuf.length = strlen(password);
+ (void) memcpy(inbuf.data, password, strlen(password));
+ free(password);
+
+#endif /* MACH_PASS */
+
+ if ((retval = krb5_mk_priv(context, auth_context, &inbuf,
+ &msg_data, &replaydata))) {
+ fprintf(stderr, "Error during Second Message Encoding: %s!\n",
+ error_message(retval));
+ free(inbuf.data);
+ return(1);
+ }
+ free(inbuf.data);
+
+ /* write private message to server */
+ if (krb5_write_message(context, local_socket, &msg_data)){
+ fprintf(stderr, "Write Error During Second Message Transmission!\n");
+ return(1);
+ }
+ free(msg_data.data);
+
+ /* Ok Now let's get the final private message */
+ if (retval = krb5_read_message(context, local_socket, &inbuf)){
+ fprintf(stderr, "Read Error During Final Reply: %s!\n",
+ error_message(retval));
+ retval = 1;
+ }
+
+ if ((retval = krb5_rd_priv(context, auth_context, &inbuf,
+ &msg_data, &replaydata))) {
+ fprintf(stderr, "Error during Final Read Decoding :%s!\n",
+ error_message(retval));
+ free(inbuf.data);
+ return(1);
+ }
+
+ decode_kadmind_reply(msg_data, &rd_priv_resp);
+
+ free(inbuf.data);
+ free(msg_data.data);
+
+ print_status_message(&rd_priv_resp,
+ "Password Modification Successful.");
+
+ return(0);
+}
--- /dev/null
+/*
+ * kadmin/client/kadmin_del.c
+ *
+ * Copyright 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ *
+ */
+
+/*
+ * Sandia National Laboratories also makes no representations about the
+ * suitability of the modifications, or additions to this software for
+ * any purpose. It is provided "as is" without express or implied warranty.
+ */
+
+
+/*
+ * kadmin_del
+ * Perform Remote Kerberos Administrative Functions
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <string.h>
+#include <com_err.h>
+
+#include <krb5.h>
+#include "adm_defs.h"
+
+void decode_kadmind_reply();
+int print_status_message();
+
+krb5_error_code
+kadm_del_user(context, auth_context, my_creds, local_socket, principal)
+ krb5_context context;
+ krb5_auth_context *auth_context;
+ int *local_socket;
+ char *principal;
+{
+ krb5_data msg_data, inbuf;
+ kadmin_requests rd_priv_resp;
+ char username[755];
+ int count;
+ krb5_replay_data replaydata;
+ krb5_error_code retval; /* return code */
+
+ if ((inbuf.data = (char *) calloc(1, 3 + sizeof(username))) == (char *) 0) {
+ fprintf(stderr, "No memory for command!\n");
+ return(1);
+ }
+
+ inbuf.data[0] = KADMIN;
+ inbuf.data[1] = DELOPER;
+ inbuf.data[2] = SENDDATA2;
+
+ if (principal && principal[0] != '\0')
+ strcpy(username, principal);
+ else {
+ count = 0;
+ do {
+ fprintf(stdout, "\nName of Principal to be Deleted: ");
+ fgets(username, sizeof(username), stdin);
+ if (username[0] == '\n')
+ fprintf(stderr, "Invalid Principal name!\n");
+ count++;
+ }
+ while (username[0] == '\n' && count < 3);
+
+ if (username[0] == '\n') {
+ fprintf(stderr, "Aborting!!\n\n");
+ return(1);
+ }
+
+ username[strlen(username) -1] = '\0';
+ }
+
+ (void) memcpy( inbuf.data + 3, username, strlen(username));
+ inbuf.length = strlen(username) + 3;
+
+ if ((retval = krb5_mk_priv(context, auth_context, &inbuf,
+ &msg_data, &replaydata))) {
+ fprintf(stderr, "Error during Second Message Encoding: %s!\n",
+ error_message(retval));
+ free(inbuf.data);
+ return(1);
+ }
+ free(inbuf.data);
+
+ /* write private message to server */
+ if (krb5_write_message(context, local_socket, &msg_data)){
+ free(msg_data.data);
+ fprintf(stderr, "Write Error During Second Message Transmission!\n");
+ return(1);
+ }
+ free(msg_data.data);
+
+ /* Ok Now let's get the final private message */
+ if (retval = krb5_read_message(context, local_socket, &inbuf)){
+ fprintf(stderr, "Read Error During Final Reply: %s!\n",
+ error_message(retval));
+ return(1);
+ }
+
+ if ((retval = krb5_rd_priv(context, auth_context, &inbuf,
+ &msg_data, &replaydata))) {
+ fprintf(stderr, "Error during Second Decoding :%s!\n",
+ error_message(retval));
+ return(1);
+ }
+
+ decode_kadmind_reply(msg_data, &rd_priv_resp);
+
+ free(inbuf.data);
+ free(msg_data.data);
+
+ print_status_message(&rd_priv_resp,
+ "Database Deletion Successful.");
+
+ return(0);
+}
--- /dev/null
+/*
+ * kadmin/client/kadmin_done.c
+ *
+ * Copyright 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ *
+ */
+
+/*
+ * Sandia National Laboratories also makes no representations about the
+ * suitability of the modifications, or additions to this software for
+ * any purpose. It is provided "as is" without express or implied warranty.
+ */
+
+
+/*
+ * kadmin_done
+ * Perform Remote Kerberos Administrative Functions
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <string.h>
+#include <com_err.h>
+
+#include <krb5.h>
+#include "adm_defs.h"
+
+krb5_error_code
+kadm_done(context, auth_context, my_creds, local_socket, seqno)
+ krb5_context context;
+ krb5_auth_context *auth_context;
+ int *local_socket;
+ krb5_int32 *seqno;
+{
+ krb5_replay_data replaydata;
+ krb5_data msg_data, inbuf;
+ krb5_error_code retval; /* return code */
+ char buf[16];
+
+ inbuf.data = buf;
+
+ inbuf.data[0] = KADMIN;
+ inbuf.data[1] = COMPLETE;
+ inbuf.data[2] = SENDDATA2;
+ inbuf.data[3] = 0xff;
+ (void) memset( inbuf.data + 4, 0, 4);
+ inbuf.length = 16;
+
+ if ((retval = krb5_mk_priv(context, auth_context, &inbuf,
+ &msg_data, &replaydata))) {
+ fprintf(stderr, "Error during Second Message Encoding: %s!\n",
+ error_message(retval));
+ return(1);
+ }
+
+ /* write private message to server */
+ if (krb5_write_message(context, local_socket, &msg_data)) {
+ free(msg_data.data);
+ fprintf(stderr, "Write Error During Second Message Transmission!\n");
+ return(1);
+ }
+ free(msg_data.data);
+ return(0);
+}
--- /dev/null
+/*
+ * kadmin/client/kadmin_inq.c
+ *
+ * Copyright 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ *
+ */
+
+/*
+ * Sandia National Laboratories also makes no representations about the
+ * suitability of the modifications, or additions to this software for
+ * any purpose. It is provided "as is" without express or implied warranty.
+ */
+
+
+/*
+ * kadmin_inq
+ * Perform Remote Kerberos Administrative Functions
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <signal.h>
+#include <string.h>
+#include <com_err.h>
+
+#include <krb5.h>
+#include "adm_defs.h"
+
+void decode_kadmind_reply();
+int print_status_message();
+
+krb5_error_code
+kadm_inq_user(context, auth_context, my_creds, local_socket, principal)
+ krb5_context context;
+ krb5_auth_context *auth_context;
+ int *local_socket;
+ char *principal;
+{
+ krb5_replay_data replaydata;
+ krb5_data msg_data, inbuf;
+ kadmin_requests rd_priv_resp;
+ char username[755];
+ int count;
+ krb5_error_code retval; /* return code */
+ char *my_data;
+
+ if ((inbuf.data = (char *) calloc(1, 3 + sizeof(username))) == (char *) 0) {
+ fprintf(stderr, "No memory for command!\n");
+ return(1);
+ }
+
+ inbuf.data[0] = KADMIN;
+ inbuf.data[1] = INQOPER;
+ inbuf.data[2] = SENDDATA2;
+
+ if (principal && principal[0] != '\0')
+ strcpy(username, principal);
+ else {
+ count = 0;
+ do {
+ fprintf(stdout, "\nName of Principal to be Displayed: ");
+ fgets(username, sizeof(username), stdin);
+ if (username[0] == '\n')
+ fprintf(stderr, "Invalid Principal name!\n");
+ count++;
+ }
+ while (username[0] == '\n' && count < 3);
+
+ if (username[0] == '\n') {
+ fprintf(stderr, "Aborting!!\n\n");
+ return(1);
+ }
+
+ username[strlen(username) -1] = '\0';
+ }
+
+ (void) memcpy( inbuf.data + 3, username, strlen(username));
+ inbuf.length = strlen(username) + 3;
+
+ if (retval = krb5_mk_priv(context, auth_context, &inbuf,
+ &msg_data, &replaydata)) {
+ fprintf(stderr, "Error during Second Message Encoding: %s!\n",
+ error_message(retval));
+ free(inbuf.data);
+ return(1);
+ }
+ free(inbuf.data);
+
+ /* write private message to server */
+ if (krb5_write_message(context, local_socket, &msg_data)){
+ fprintf(stderr, "Write Error During Second Message Transmission!\n");
+ return(1);
+ }
+ free(msg_data.data);
+
+ /* Ok Now let's get the private message */
+ if ((retval = krb5_read_message(context, local_socket, &inbuf))){
+ fprintf(stderr, "Read Error During Second Reply: %s!\n",
+ error_message(retval));
+ return(1);
+ }
+
+ if (retval = krb5_rd_priv(context, auth_context, &inbuf,
+ &msg_data, &replaydata)) {
+ fprintf(stderr, "Error during Second Read Decoding :%s!\n",
+ error_message(retval));
+ free(inbuf.data);
+ return(1);
+ }
+ free(inbuf.data);
+
+ if (!msg_data.data) {
+ fprintf(stderr, "kadm_inq_user: Error - empty message received!\n\n");
+ return(0);
+ }
+
+ if (msg_data.data[2] == KADMBAD) {
+ decode_kadmind_reply(msg_data, &rd_priv_resp);
+
+ if (rd_priv_resp.message) {
+ fprintf(stderr, "%s\n\n", rd_priv_resp.message);
+ free(rd_priv_resp.message);
+ } else
+ fprintf(stderr, "Generic error from server.\n\n");
+ return(0);
+ }
+
+ my_data = (char *)malloc(msg_data.length + 1);
+ if (!my_data) {
+ fprintf(stderr, "kadmin_inq: Couldn't allocate space for my_data!\n");
+ exit(1);
+ }
+ memcpy(my_data, msg_data.data, msg_data.length);
+ my_data[msg_data.length] = 0;
+
+ /* Print Inquiry Information */
+ fprintf(stdout, "%s\n", my_data);
+ free(my_data);
+ free(msg_data.data);
+
+ if ((inbuf.data = (char *) calloc(1, 3)) == (char *) 0) {
+ fprintf(stderr, "inbuf.data allocation error!\n");
+ return(1);
+ }
+
+ inbuf.data[0] = KADMIN;
+ inbuf.data[1] = KADMGOOD;
+ inbuf.length = 2;
+
+ if (retval = krb5_mk_priv(context, auth_context, &inbuf,
+ &msg_data, &replaydata)) {
+ fprintf(stderr, "Error during Second Message Encoding: %s!\n",
+ error_message(retval));
+ free(inbuf.data);
+ return(1);
+ }
+ free(inbuf.data);
+
+ /* write private message to server */
+ if (krb5_write_message(context, local_socket, &msg_data)){
+ fprintf(stderr, "Write Error During Second Message Transmission!\n");
+ free(msg_data.data);
+ return(1);
+ }
+ free(msg_data.data);
+
+ /* Ok Now let's get the final private message */
+ if (retval = krb5_read_message(context, local_socket, &inbuf)){
+ fprintf(stderr, "Read Error During Final Reply: %s!\n",
+ error_message(retval));
+ retval = 1;
+ }
+
+ if (retval = krb5_rd_priv(context, auth_context, &inbuf,
+ &msg_data, &replaydata)) {
+ fprintf(stderr, "Error during Final Read Decoding :%s!\n",
+ error_message(retval));
+ free(inbuf.data);
+ return(1);
+ }
+ free(inbuf.data);
+
+ decode_kadmind_reply(msg_data, &rd_priv_resp);
+
+ free(inbuf.data);
+ free(msg_data.data);
+
+ print_status_message(&rd_priv_resp,
+ "Password Inquiry Successful.");
+
+ return(0);
+}
--- /dev/null
+/*
+ * kadmin/client/kadmin_mod.c
+ *
+ * Copyright 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ *
+ */
+
+/*
+ * Sandia National Laboratories also makes no representations about the
+ * suitability of the modifications, or additions to this software for
+ * any purpose. It is provided "as is" without express or implied warranty.
+ */
+
+
+/*
+ * kadmin_mod
+ * Perform Remote Kerberos Administrative Functions
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <signal.h>
+#include <string.h>
+#include <com_err.h>
+
+#include <krb5.h>
+#include "adm_defs.h"
+
+void decode_kadmind_reply();
+int print_status_message();
+
+krb5_error_code
+kadm_mod_user(context, auth_context, my_creds, local_socket, principal)
+ krb5_context context;
+ krb5_auth_context *auth_context;
+ krb5_creds *my_creds;
+ int *local_socket;
+ char *principal;
+{
+ krb5_data msg_data, inbuf;
+ kadmin_requests rd_priv_resp;
+ char username[755];
+ int count;
+ krb5_replay_data replaydata;
+ krb5_error_code retval; /* return code */
+
+ if ((inbuf.data = (char *) calloc(1, 3 + sizeof(username))) == (char *) 0) { fprintf(stderr, "No memory for command!\n");
+ exit(1);
+ }
+
+ inbuf.data[0] = KADMIN;
+ inbuf.data[1] = MODOPER;
+ inbuf.data[2] = SENDDATA2;
+
+ if (principal && principal[0] != '\0')
+ strcpy(username, principal);
+ else {
+ count = 0;
+ do {
+ fprintf(stdout, "\nName of Principal to be Modified: ");
+ fgets(username, sizeof(username), stdin);
+ if (username[0] == '\n')
+ fprintf(stderr, "Invalid Principal name!\n");
+ count++;
+ }
+ while (username[0] == '\n' && count < 3);
+
+ if (username[0] == '\n') {
+ fprintf(stderr, "Aborting!!\n\n");
+ return(1);
+ }
+
+ username[strlen(username) -1] = '\0';
+ }
+
+ (void) memcpy( inbuf.data + 3, username, strlen(username));
+ inbuf.length = strlen(username) + 3;
+
+ if ((retval = krb5_mk_priv(context, auth_context, &inbuf,
+ &msg_data, &replaydata))) {
+ fprintf(stderr, "Error during Second Message Encoding: %s!\n",
+ error_message(retval));
+ free(inbuf.data);
+ return(1);
+ }
+ free(inbuf.data);
+
+ /* write private message to server */
+ if (krb5_write_message(context, local_socket, &msg_data)){
+ fprintf(stderr, "Write Error During Second Message Transmission!\n");
+ return(1);
+ }
+ free(msg_data.data);
+
+ /* Ok Now let's get the private message */
+ if (retval = krb5_read_message(context, local_socket, &inbuf)){
+ fprintf(stderr, "Read Error During Second Reply: %s!\n",
+ error_message(retval));
+ return(1);
+ }
+
+ if ((retval = krb5_rd_priv(context, auth_context, &inbuf,
+ &msg_data, &replaydata))) {
+ fprintf(stderr, "Error during Second Read Decoding :%s!\n",
+ error_message(retval));
+ free(inbuf.data);
+ return(1);
+ }
+ free(inbuf.data);
+
+ if (msg_data.data[2] == KADMBAD) {
+ decode_kadmind_reply(msg_data, &rd_priv_resp);
+
+ if (rd_priv_resp.message) {
+ fprintf(stderr, "%s\n\n", rd_priv_resp.message);
+ free(rd_priv_resp.message);
+ } else
+ fprintf(stderr, "Generic error from server.\n\n");
+ free(msg_data.data);
+ return(0);
+ }
+ free(msg_data.data);
+
+ kadm_snd_mod(context, auth_context, my_creds, local_socket);
+
+ if ((inbuf.data = (char *) calloc(1, 2)) == (char *) 0) {
+ fprintf(stderr, "No memory for command!\n");
+ return(1);
+ }
+
+
+ inbuf.data[0] = KADMIN;
+ inbuf.data[1] = KADMGOOD;
+ inbuf.data[2] = SENDDATA3;
+ inbuf.length = 3;
+
+ if ((retval = krb5_mk_priv(context, auth_context, &inbuf,
+ &msg_data, &replaydata))) {
+ fprintf(stderr, "Error during Second Message Encoding: %s!\n",
+ error_message(retval));
+ free(inbuf.data);
+ return(1);
+ }
+ free(inbuf.data);
+
+ /* write private message to server */
+ if (krb5_write_message(context, local_socket, &msg_data)){
+ fprintf(stderr, "Write Error During Second Message Transmission!\n");
+ free(msg_data.data);
+ return(1);
+ }
+ free(msg_data.data);
+
+ /* Ok Now let's get the final private message */
+ if (retval = krb5_read_message(context, local_socket, &inbuf)){
+ fprintf(stderr, "Read Error During Final Reply: %s!\n",
+ error_message(retval));
+ retval = 1;
+ }
+
+ if ((retval = krb5_rd_priv(context, auth_context, &inbuf,
+ &msg_data, &replaydata))) {
+ fprintf(stderr, "Error during Final Read Decoding :%s!\n",
+ error_message(retval));
+ free(inbuf.data);
+ return(1);
+ }
+
+
+ decode_kadmind_reply(msg_data, &rd_priv_resp);
+
+ free(inbuf.data);
+ free(msg_data.data);
+
+ print_status_message(&rd_priv_resp,
+ "Database Modification Successful.");
+
+ return(0);
+}
--- /dev/null
+/*
+ * kadmin/client/kadmin_msnd.c
+ *
+ * Copyright 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ *
+ */
+
+/*
+ * Sandia National Laboratories also makes no representations about the
+ * suitability of the modifications, or additions to this software for
+ * any purpose. It is provided "as is" without express or implied warranty.
+ */
+
+
+/*
+ * kadmin_snd_mod
+ * Perform Remote Kerberos Administrative Functions
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <signal.h>
+#include <string.h>
+#include <com_err.h>
+
+#include <sys/param.h>
+#include <pwd.h>
+
+#include <sys/stat.h>
+
+#include <krb5.h>
+#include "adm_defs.h"
+
+#ifndef MAXPATHLEN
+#define MAXPATHLEN 1024
+#endif
+
+krb5_error_code
+kadm_snd_mod(context, auth_context, my_creds, local_socket)
+ krb5_context context;
+ krb5_auth_context *auth_context;
+ krb5_creds *my_creds;
+ int *local_socket;
+{
+ krb5_replay_data replaydata;
+ krb5_error_code retval; /* return code */
+ krb5_data msg_data, inbuf;
+ char mod_type[10];
+ char attrib[20];
+ char version[10];
+ int value;
+ int valid_command;
+ int i;
+
+ for ( ; ; ) {
+ valid_command = 0;
+repeat1:
+#ifdef SANDIA
+ fprintf(stdout, "\nParameter Type to be Modified (fcnt, vno, attr, or q): ");
+#else
+ fprintf(stdout, "\nParameter Type to be Modified (vno, attr, or q): ");
+#endif
+
+ (void) fgets(mod_type, 10, stdin);
+ mod_type[strlen(mod_type) - 1] = '\0';
+
+ if ((inbuf.data = (char *) calloc(1, 80)) == (char *) 0) {
+ fprintf(stderr, "No memory for command!\n");
+ exit(1);
+ }
+
+ if (!strcmp(mod_type, "q")) {
+ free(inbuf.data);
+ goto alldone;
+ }
+#ifdef SANDIA
+ if (!strcmp(mod_type, "fcnt")) {
+ valid_command = 1;
+repeat_cnt:
+ fprintf(stdout, "\nFailure Count: ");
+ (void) fgets(version, sizeof(version), stdin);
+ /* Make sure version is null terminated */
+ version[sizeof(version) -1] = '\0';
+ /* Strip linefeed */
+ if (version[strlen(version) - 1] == '\n')
+ version[strlen(version) - 1] = '\0';
+ if (!strcmp(version, "q")) {
+ free(inbuf.data);
+ goto alldone;
+ }
+ value = -1;
+ sscanf(version,"%d",&value);
+ if (value < 0 || value > 10 ) {
+ fprintf(stderr, "Value must be between 0 and 10!\n");
+ goto repeat_cnt;
+ }
+ inbuf.data[3] = KMODFCNT;
+ (void) memcpy(inbuf.data + 4, version, strlen(version));
+ inbuf.length = strlen(version) + 4;
+ }
+#endif
+ if (!strcmp(mod_type, "vno")) {
+ valid_command = 1;
+repeat2:
+ fprintf(stdout, "\nVersion Number: ");
+ (void) fgets(version, sizeof(version), stdin);
+ /* Make sure version is null terminated */
+ version[sizeof(version) -1] = '\0';
+ /* Strip linefeed */
+ if (version[strlen(version) - 1] == '\n')
+ version[strlen(version) - 1] = '\0';
+ if (!strcmp(version, "q")) {
+ free(inbuf.data);
+ goto alldone;
+ }
+ value = -1;
+ sscanf(version,"%d",&value);
+ if (value < 0 || value > 255 ) {
+ fprintf(stderr, "Value must be between 0 and 255!\n");
+ goto repeat2;
+ }
+ inbuf.data[3] = KMODVNO;
+ (void) memcpy(inbuf.data + 4, version, strlen(version));
+ inbuf.length = strlen(version) + 4;
+ }
+
+ if (!strcmp(mod_type, "attr")) {
+ valid_command = 1;
+repeat3:
+ fprintf(stdout, "\nAttribute: ");
+ fgets(attrib, 20, stdin);
+ attrib[strlen(attrib) - 1] = '\0';
+ for (i = 0; attrib[i] != '\0'; i++)
+ if (isupper(attrib[i]))
+ attrib[i] = tolower(attrib[i]);
+
+ inbuf.data[3] = KMODATTR;
+ inbuf.data[4] = BADATTR;
+ inbuf.length = 5;
+ if (!strcmp(attrib, "post")) inbuf.data[4] = ATTRPOST;
+ if (!strcmp(attrib, "nopost")) inbuf.data[4] = ATTRNOPOST;
+ if (!strcmp(attrib, "forward")) inbuf.data[4] = ATTRFOR;
+ if (!strcmp(attrib, "noforward")) inbuf.data[4] = ATTRNOFOR;
+ if (!strcmp(attrib, "tgt")) inbuf.data[4] = ATTRTGT;
+ if (!strcmp(attrib, "notgt")) inbuf.data[4] = ATTRNOTGT;
+ if (!strcmp(attrib, "ren")) inbuf.data[4] = ATTRREN;
+ if (!strcmp(attrib, "noren")) inbuf.data[4] = ATTRNOREN;
+ if (!strcmp(attrib, "proxy")) inbuf.data[4] = ATTRPROXY;
+ if (!strcmp(attrib, "noproxy")) inbuf.data[4] = ATTRNOPROXY;
+ if (!strcmp(attrib, "dskey")) inbuf.data[4] = ATTRDSKEY;
+ if (!strcmp(attrib, "nodskey")) inbuf.data[4] = ATTRNODSKEY;
+ if (!strcmp(attrib, "lock")) inbuf.data[4] = ATTRLOCK;
+ if (!strcmp(attrib, "unlock")) inbuf.data[4] = ATTRUNLOCK;
+ if (!strcmp(attrib, "svr")) inbuf.data[4] = ATTRSVR;
+ if (!strcmp(attrib, "nosvr")) inbuf.data[4] = ATTRNOSVR;
+
+#ifdef SANDIA
+ if (!strcmp(attrib, "preauth")) inbuf.data[4] = ATTRPRE;
+ if (!strcmp(attrib, "nopreauth")) inbuf.data[4] = ATTRNOPRE;
+ if (!strcmp(attrib, "pwok")) inbuf.data[4] = ATTRPWOK;
+ if (!strcmp(attrib, "pwchange")) inbuf.data[4] = ATTRPWCHG;
+ if (!strcmp(attrib, "sid")) inbuf.data[4] = ATTRSID;
+ if (!strcmp(attrib, "nosid")) inbuf.data[4] = ATTRNOSID;
+#endif
+ if (!strcmp(attrib, "q")){
+ free(inbuf.data);
+ goto alldone;
+ }
+ if (inbuf.data[4] == BADATTR) {
+ fprintf(stderr, "Valid Responses are:\n");
+ fprintf(stderr, "post/nopost - Allow/Disallow postdating\n");
+ fprintf(stderr, "forward/noforward - Allow/Disallow forwarding\n");
+ fprintf(stderr, "tgt/notgt - Allow/Disallow initial tickets\n");
+ fprintf(stderr, "ren/noren - Allow/Disallow renewable tickets\n");
+ fprintf(stderr,
+ "proxy/noproxy - Allow/Disallow proxiable tickets\n");
+ fprintf(stderr,
+ "dskey/nodskey - Allow/Disallow Duplicate Session Keys\n");
+ fprintf(stderr, "lock/unlock - Lock/Unlock client\n");
+ fprintf(stderr,
+ "svr/nosvr - Allow/Disallow Use of Principal as Server\n");
+#ifdef SANDIA
+ fprintf(stderr,
+ "preauth/nopreauth - Require/Do Not Require preauthentication\n");
+ fprintf(stderr,
+ "pwok/pwchange - Password is OK/Needs to be changed\n");
+ fprintf(stderr,
+ "sid/nosid - Require/Do Not Require Hardware Authentication\n");
+#endif
+ fprintf(stderr, "q - Quit from setting attributes.\n");
+ goto repeat3;
+ }
+ }
+
+ if (!valid_command) {
+ free(inbuf.data);
+ fprintf(stderr, "Invalid command - Try Again\n");
+ goto repeat1;
+ }
+
+ inbuf.data[0] = KADMIN;
+ inbuf.data[1] = MODOPER;
+ inbuf.data[2] = SENDDATA3;
+
+ if ((retval = krb5_mk_priv(context, auth_context, &inbuf,
+ &msg_data, &replaydata))) {
+ fprintf(stderr, "Error during Second Message Encoding: %s!\n",
+ error_message(retval));
+ free(inbuf.data);
+ return(1);
+ }
+ free(inbuf.data);
+
+ /* write private message to server */
+ if (krb5_write_message(context, local_socket, &msg_data)) {
+ fprintf(stderr, "Write Error During Second Message Transmission!\n");
+ return(1);
+ }
+ free(msg_data.data);
+
+ /* Ok Now let's get the private message */
+ if (retval = krb5_read_message(context, local_socket, &inbuf)){
+ fprintf(stderr, "Read Error During Second Reply: %s!\n",
+ error_message(retval));
+ return(1);
+ }
+
+ if ((retval = krb5_rd_priv(context, auth_context, &inbuf,
+ &msg_data, &replaydata))) {
+ fprintf(stderr, "Error during Second Read Decoding :%s!\n",
+ error_message(retval));
+ free(inbuf.data);
+ return(1);
+ }
+ free(inbuf.data);
+ } /* for */
+
+alldone:
+ if ((inbuf.data = (char *) calloc(1, 80)) == (char *) 0) {
+ fprintf(stderr, "No memory for command!\n");
+ exit(1);
+ }
+
+ inbuf.data[0] = KADMIN;
+ inbuf.data[1] = KADMGOOD;
+ inbuf.data[2] = SENDDATA3;
+ inbuf.length = 3;
+
+ if ((retval = krb5_mk_priv(context, auth_context, &inbuf,
+ &msg_data, &replaydata))) {
+ fprintf(stderr, "Error during Second Message Encoding: %s!\n",
+ error_message(retval));
+ free(inbuf.data);
+ return(1);
+ }
+ free(inbuf.data);
+
+ /* write private message to server */
+ if (krb5_write_message(context, local_socket, &msg_data)) {
+ fprintf(stderr, "Write Error During Second Message Transmission!\n");
+ return(1);
+ }
+ free(msg_data.data);
+
+ return(0);
+}
--- /dev/null
+AC_INIT(configure.in)
+WITH_CCOPTS
+AC_SET_BUILDTOP
+CONFIG_DIRS(client kpasswd server)
+MAKE_SUBDIRS("making",all)
+MAKE_SUBDIRS("cleaning",clean)
+MAKE_SUBDIRS("installing",install)
+CONFIG_RULES
+WITH_KRB5ROOT
+V5_AC_OUTPUT_MAKEFILE
--- /dev/null
+# Sanitize.in for Kerberos V5
+
+# Each directory to survive it's way into a release will need a file
+# like this one called "./.Sanitize". All keyword lines must exist,
+# and must exist in the order specified by this file. Each directory
+# in the tree will be processed, top down, in the following order.
+
+# Hash started lines like this one are comments and will be deleted
+# before anything else is done. Blank lines will also be squashed
+# out.
+
+# The lines between the "Do-first:" line and the "Things-to-keep:"
+# line are executed as a /bin/sh shell script before anything else is
+# done in this
+
+Do-first:
+
+# All files listed between the "Things-to-keep:" line and the
+# "Files-to-sed:" line will be kept. All other files will be removed.
+# Directories listed in this section will have their own Sanitize
+# called. Directories not listed will be removed in their entirety
+# with rm -rf.
+
+Things-to-keep:
+
+.cvsignore
+ChangeLog
+Makefile.in
+configure
+configure.in
+kpasswd.M
+kpasswd.c
+networked.c
+
+Things-to-lose:
+
+Do-last:
+
+# End of file.
--- /dev/null
+Fri Mar 17 15:36:07 1995 Chris Provenzano (proven@mit.edu)
+
+ * kpasswd.c: Cast malloc() return value to shut compiler up.
+
+Fri Mar 10 11:09:34 1995 Chris Provenzano (proven@mit.edu)
+
+ * kpasswd.c: Use new calling convention for krb5_sendauth(),
+ krb5_mk_priv(), and krb5_rd_priv().
+
+Thu Mar 2 12:25:29 1995 Theodore Y. Ts'o <tytso@dcl>
+
+ * Makefile.in (ISODELIB): Remove reference to $(ISODELIB).
+
+Wed Mar 1 16:29:34 1995 Theodore Y. Ts'o <tytso@dcl>
+
+ * configure.in: Remove ISODE_INCLUDE, replace check for -lsocket
+ and -lnsl with WITH_NETLIB check.
+
+Tue Feb 28 02:21:41 1995 John Gilmore (gnu at toad.com)
+
+ * kpasswd.c: Avoid <krb5/...> includes.
+
+Tue Feb 14 15:30:55 1995 Chris Provenzano (proven@mit.edu)
+
+ * kpasswd.c: Call krb5_sendauth(), krb5_get_credentials()
+ with new calling convention.
+
+Fri Feb 10 17:48:05 1995 Theodore Y. Ts'o <tytso@dcl>
+
+ * kpasswd.c: Don't include <krb5/asn.1/encode.h>; use <krb5/asn1.h>.
+
+Mon Feb 06 17:19:04 1995 Chris Provenzano (proven@mit.edu)
+
+ * kpasswd.c Removed krb5_keytype, changed krb5_enctype to
+ krb5_enctype *, changed krb5_preauthtype to krb5_preauthtype *
+ for krb5_get_in_tkt_with_password() rotuine.
+
+Wed Jan 25 16:54:40 1995 Chris Provenzano (proven@mit.edu)
+
+ * Removed all narrow types and references to wide.h and narrow.h
+
+Fri Jan 13 15:23:47 1995 Chris Provenzano (proven@mit.edu)
+
+ * Added krb5_context to all krb5_routines
+
+Tue Dec 27 06:09:03 1994 Richard Basch (probe@tardis)
+
+ * configure.in:
+ combined KRB5_UTPID, KRB5_UTTYPE, and KRB5_UTHOST
+ into CHECK_UTMP macro (and added additional checks)
+
+Fri Nov 18 01:08:39 1994 Mark Eichin <eichin@cygnus.com>
+
+ * configure.in: use new macros KRB5_UTPID, KRB5_UTTYPE, and
+ KRB5_UTHOST (from epeisach).
+
+Wed Oct 19 12:18:26 1994 Theodore Y. Ts'o (tytso@dcl)
+
+ * Makefile.in: Look for man page in the source directory.
+
+Fri Sep 30 22:30:21 1994 Theodore Y. Ts'o (tytso@dcl)
+
+ * kpasswd.c: Add placeholders for magic numbers
+
+Thu Sep 29 22:40:10 1994 Theodore Y. Ts'o (tytso@dcl)
+
+ * Makefile.in: relink executable if libraries change
+
+Tue Aug 9 21:42:02 1994 Tom Yu (tlyu@dragons-lair)
+
+ * networked.c: yet another utent fix
+
+Sat Jul 16 02:51:25 1994 Tom Yu (tlyu at dragons-lair)
+
+ * kpasswd.c (get_first_ticket): fix error codes
+
--- /dev/null
+CFLAGS = $(CCOPTS) $(DEFS) $(LOCALINCLUDE)
+LDFLAGS = -g
+
+COMERRLIB=$(BUILDTOP)/util/et/libcom_err.a
+SSLIB=$(BUILDTOP)/util/ss/libss.a
+DBMLIB=
+KDBLIB=$(TOPLIBD)/libkdb5.a
+
+all::
+
+KLIB = $(TOPLIBD)/libkrb5.a $(TOPLIBD)/libcrypto.a $(SSLIB) $(COMERRLIB) $(DBMLIB)
+DEPKLIB = $(TOPLIBD)/libkrb5.a $(TOPLIBD)/libcrypto.a $(SSLIB) $(COMERRLIB) $(DBMLIB)
+
+SRCS = \
+ $(srcdir)/networked.c \
+ $(srcdir)/kpasswd.c
+
+OBJS = \
+ networked.o \
+ kpasswd.o
+
+
+all:: kpasswd
+
+kpasswd: $(KDBDEPLIB) $(OBJS) $(DEPKLIB)
+ $(CC) $(CFLAGS) -o kpasswd $(OBJS) $(KLIB) $(LIBS)
+
+install::
+ $(INSTALL_PROGRAM) kpasswd ${DESTDIR}$(CLIENT_BINDIR)/kpasswd
+ $(INSTALL_DATA) $(srcdir)/kpasswd.M ${DESTDIR}$(CLIENT_MANDIR)/kpasswd.1
+
+clean::
+ $(RM) kpasswd
+
--- /dev/null
+AC_INIT(kpasswd.c)
+WITH_CCOPTS
+CONFIG_RULES
+AC_SET_BUILDTOP
+AC_PROG_INSTALL
+WITH_NETLIB
+AC_HAVE_HEADERS(unistd.h)
+CHECK_UTMP
+AC_FUNC_CHECK(getutent,AC_DEFINE(HAVE_GETUTENT))
+ET_RULES
+KRB_INCLUDE
+WITH_KRB5ROOT
+V5_AC_OUTPUT_MAKEFILE
--- /dev/null
+.\" this should not be empty
--- /dev/null
+/*
+ * kadmin/kpasswd/kpasswd.c
+ *
+ * Copyright 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ *
+ * change your password with kerberos
+ */
+
+/*
+ * Sandia National Laboratories also makes no representations about the
+ * suitability of the modifications, or additions to this software for
+ * any purpose. It is provided "as is" without express or implied warranty.
+ */
+
+
+/*
+ * kpasswd
+ * change your password with Version 5 Kerberos
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <signal.h>
+
+#include <sys/param.h>
+#include <pwd.h>
+
+#include <sys/stat.h>
+
+#include "krb5.h"
+#ifdef USE_STRING_H
+#include <string.h>
+#else
+#include <strings.h>
+#endif
+#include "com_err.h"
+#include "adm_defs.h"
+
+#ifndef MAXPATHLEN
+#define MAXPATHLEN 1024
+#endif
+
+static krb5_error_code adm5_init_link
+ PROTOTYPE((krb5_context,
+ krb5_data *,
+ int *));
+
+static krb5_error_code get_first_ticket
+ PROTOTYPE((krb5_context,
+ krb5_ccache,
+ krb5_principal,
+ krb5_creds *));
+
+krb5_error_code print_and_choose_password
+ PROTOTYPE((char *, krb5_data *));
+
+struct sockaddr_in local_sin, remote_sin;
+
+
+extern char *krb5_default_pwd_prompt1;
+
+main(argc,argv)
+ int argc;
+ char *argv[];
+{
+ krb5_context context;
+ krb5_ccache cache = NULL;
+ char cache_name[255];
+ krb5_flags cc_flags;
+
+ krb5_address local_addr, foreign_addr;
+
+ struct passwd *pw;
+
+ krb5_principal client;
+
+ char default_name[256];
+ char *client_name; /* Single string representation of client id */
+
+ krb5_data requested_realm;
+
+ char input_string[768];
+
+ krb5_error_code retval; /* return code */
+
+ int local_socket;
+
+ krb5_error *err_ret;
+ krb5_ap_rep_enc_part *rep_ret;
+
+ kadmin_requests rd_priv_resp;
+
+ krb5_data msg_data, inbuf;
+ krb5_int32 seqno;
+
+ krb5_creds my_creds, * new_creds;
+ char *new_password;
+ int new_pwsize;
+
+ krb5_auth_context * new_auth_context;
+ krb5_replay_data replaydata;
+
+#ifdef SANDIA
+ extern int networked();
+ int krb_secure;
+ struct stat statbuf;
+#endif /* SANDIA */
+
+#ifdef SANDIA /* Allow or Disallow Remote Clients to Modify Passwords */
+/*
+ * If a Client Modifies a Password using kpasswd on this host
+ * from a remote host or network terminal, the Password selected
+ * is transmitted across the network in Cleartext.
+ *
+ * The systems administrator can disallow "remote" kpasswd usage by
+ * creating the file "/etc/krb.secure"
+ */
+
+ krb_secure = 0;
+/*
+ * First check to see if the file /etc/krb.secure exists.
+ * If it does then krb_secure to 1.
+ */
+
+ if (stat("/etc/krb.secure", &statbuf) == 0) krb_secure = 1;
+
+/*
+ * Check to see if this process is tied to a physical terminal.
+ * Network() verifies the terminal device is not a pseudo tty
+ */
+ if (networked() && krb_secure) {
+ fprintf(stderr,"Sorry but you cannot %s from a\n", argv[0]);
+ fprintf(stderr," pseudo tty terminal!\n");
+ retval = 1;
+ goto finish;
+ }
+#endif
+
+ /* (3 * 255) + 1 (/) + 1 (@) + 1 (NULL) */
+ if ((client_name = (char *) calloc (1, (3 * 256))) == NULL) {
+ fprintf(stderr, "No Memory for Client_name!\n");
+ retval = 1;
+ goto finish;
+ }
+
+ if ((requested_realm.data = (char *) calloc (1, 256)) == NULL) {
+ fprintf(stderr, "No Memory for realm_name!\n");
+ retval = 1;
+ free(client_name);
+ goto finish;
+ }
+
+ krb5_init_context(&context);
+ krb5_init_ets(context);
+ memset((char *) default_name, 0, sizeof(default_name));
+
+ switch (argc) {
+ case 1: /* No User Specified */
+
+ /* Identify Default Credentials Cache */
+ if ((retval = krb5_cc_default(context, &cache))) {
+ fprintf(stderr, "Error while getting default ccache!\n");
+ goto finish;
+ }
+
+/*
+ * Attempt to Modify Credentials Cache
+ * retval == 0 ==> ccache Exists - Use It
+ * retval == ENOENT ==> No Entries, but ccache Exists
+ * retval != 0 ==> Assume ccache does NOT Exist
+ */
+ cc_flags = 0;
+ if ((retval = krb5_cc_set_flags(context, cache, cc_flags))) {
+ /* Search passwd file for client */
+ pw = getpwuid((int) getuid());
+ if (pw) {
+ (void) strcpy(default_name, pw->pw_name);
+ } else {
+ fprintf(stderr,
+ "Unable to Identify Customer from Password File!\n");
+ retval = 1;
+ goto finish;
+ }
+
+ /* Use this to get default_realm and format client_name */
+ if ((retval = krb5_parse_name(context,default_name, &client))) {
+ fprintf(stderr, "Unable to Parse Client Name!\n");
+ goto finish;
+ }
+
+ if ((retval = krb5_unparse_name(context,client,&client_name))) {
+ fprintf(stderr, "Unable to Parse Client Name!\n");
+ goto finish;
+ }
+
+ requested_realm.length = client->realm.length;
+ memcpy((char *) requested_realm.data,
+ (char *) client->realm.data,
+ requested_realm.length);
+ } else {
+ /* Read Client from Cache */
+ if ((retval = krb5_cc_get_principal(context, cache,
+ (krb5_principal *) &client))) {
+ fprintf(stderr,
+ "Unable to Read Customer Credentials File!\n");
+ goto finish;
+ }
+
+ if ((retval = krb5_unparse_name(context,client,&client_name))) {
+ fprintf(stderr, "Unable to Parse Client Name!\n");
+ goto finish;
+ }
+
+ requested_realm.length = client->realm.length;
+ memcpy((char *) requested_realm.data,
+ (char *) client->realm.data,
+ requested_realm.length);
+
+ (void) krb5_cc_close(context, cache);
+ }
+ break;
+
+ case 2: /* Client Gave us a Token - Use it */
+ /* Hand Parse Entry */
+ strcpy(input_string, argv[1]);
+
+ if (retval = krb5_parse_name(context, input_string, &client)) {
+ fprintf(stderr, "Error Parsing -u option contents!\n");
+ exit(0);
+ }
+ requested_realm.length = client->realm.length;
+ memcpy((char *) requested_realm.data,
+ (char *) client->realm.data,
+ requested_realm.length);
+
+ break;
+
+ default:
+ usage();
+ break;
+ }
+
+ /* Create credential cache for changepw */
+ (void) sprintf(cache_name, "FILE:/tmp/tkt_cpw_%d", getpid());
+
+ if ((retval = krb5_cc_resolve(context, cache_name, &cache))) {
+ fprintf(stderr, "Unable to Resolve Cache: %s\n", cache_name);
+ }
+
+ if ((retval = krb5_cc_initialize(context, cache, client))) {
+ fprintf(stderr, "Error initializing cache: %s\n", cache_name);
+ goto finish;
+ }
+
+/*
+ * Verify User by Obtaining Initial Credentials prior to Initial Link
+ */
+
+ if ((retval = get_first_ticket(context, cache, client, &my_creds))) {
+ goto finish;
+ }
+
+ /* Initiate Link to Server */
+ if ((retval = adm5_init_link(context, &requested_realm, &local_socket))) {
+ goto finish;
+ }
+
+#ifdef unicos61
+#define SIZEOF_INADDR SIZEOF_in_addr
+#else
+#define SIZEOF_INADDR sizeof(struct in_addr)
+#endif
+
+ /* V4 kpasswd Protocol Hack */
+ {
+ int msg_length = 0;
+
+ retval = krb5_net_write(context, local_socket, (char *) &msg_length + 2, 2);
+ if (retval < 0) {
+ fprintf(stderr, "krb5_net_write failure!\n");
+ goto finish;
+ }
+
+ }
+
+ local_addr.addrtype = ADDRTYPE_INET;
+ local_addr.length = SIZEOF_INADDR ;
+ local_addr.contents = (krb5_octet *)&local_sin.sin_addr;
+
+ foreign_addr.addrtype = ADDRTYPE_INET;
+ foreign_addr.length = SIZEOF_INADDR ;
+ foreign_addr.contents = (krb5_octet *)&remote_sin.sin_addr;
+
+ krb5_auth_con_init(context, &new_auth_context);
+ krb5_auth_con_setflags(context, new_auth_context,
+ KRB5_AUTH_CONTEXT_RET_SEQUENCE);
+
+ krb5_auth_con_setaddrs(context, new_auth_context,
+ &local_addr, &foreign_addr);
+
+ /* call Kerberos library routine to obtain an authenticator,
+ pass it over the socket to the server, and obtain mutual
+ authentication. */
+
+ inbuf.data = ADM_CPW_VERSION;
+ inbuf.length = strlen(ADM_CPW_VERSION);
+
+ if ((retval = krb5_sendauth(context, &new_auth_context,
+ (krb5_pointer) &local_socket,
+ ADM_CPW_VERSION,
+ my_creds.client,
+ my_creds.server,
+ AP_OPTS_MUTUAL_REQUIRED,
+ &inbuf,
+ NULL,
+ cache,
+ &err_ret,
+ &rep_ret, NULL))) {
+ fprintf(stderr, "Error while performing sendauth: %s!\n",
+ error_message(retval));
+ goto finish;
+ }
+
+ /* Get credentials : to use for safe and private messages */
+ /* No need to pass my_creds because it's uninizialized. */
+ if (retval = krb5_get_credentials(context,0,cache,&my_creds,&new_creds)){
+ fprintf(stderr, "Error Obtaining Credentials: %s!\n",
+ error_message(retval));
+ goto finish;
+ }
+
+ /* Read back what the server has to say... */
+
+ if (retval = krb5_read_message(context, &local_socket, &inbuf)){
+ fprintf(stderr, " Read Message Error: %s!\n",
+ error_message(retval));
+ goto finish;
+ }
+ if ((inbuf.length != 2) || (inbuf.data[0] != KADMIND) ||
+ (inbuf.data[1] != KADMSAG)){
+ fprintf(stderr, " Invalid ack from admin server.\n");
+ goto finish;
+ }
+
+ inbuf.length = 2;
+ inbuf.data[0] = KPASSWD;
+ inbuf.data[1] = CHGOPER;
+ if ((retval = krb5_mk_priv(context, new_auth_context, &inbuf,
+ &msg_data, &replaydata))) {
+ fprintf(stderr, "Error during First Message Encoding: %s!\n",
+ error_message(retval));
+ goto finish;
+ }
+ free(inbuf.data);
+
+ /* write private message to server */
+ if (krb5_write_message(context, &local_socket, &msg_data)){
+ fprintf(stderr, "Write Error During First Message Transmission!\n");
+ retval = 1;
+ goto finish;
+ }
+ free(msg_data.data);
+
+#ifdef MACH_PASS /* Machine-generated Passwords */
+ /* Ok Now let's get the private message */
+ if (retval = krb5_read_message(context, &local_socket, &inbuf)){
+ fprintf(stderr, "Read Error During First Reply: %s!\n",
+ error_message(retval));
+ retval = 1;
+ goto finish;
+ }
+
+ if ((retval = krb5_rd_priv(context, new_auth_context, &inbuf,
+ &msg_data, &replaydata))) {
+ fprintf(stderr, "Error during First Read Decoding: %s!\n",
+ error_message(retval));
+ goto finish;
+ }
+ free(inbuf.data);
+#endif
+
+ if ((new_password = (char *) calloc (1, ADM_MAX_PW_LENGTH+1)) == NULL) {
+ fprintf(stderr, "Unable to Allocate Space for New Password!\n");
+ goto finish;
+ }
+
+#ifdef MACH_PASS /* Machine-generated passwords */
+ /* Offer Client Password Choices */
+ if ((retval = print_and_choose_password(new_password,
+ &msg_data))) {
+ (void) memset((char *) new_password, 0, ADM_MAX_PW_LENGTH+1);
+ free(new_password);
+ goto finish;
+ }
+#else
+ new_pwsize = ADM_MAX_PW_LENGTH+1;
+ putchar('\n');
+ if ((retval = krb5_read_password(context,
+ "Enter new password: ",
+ "Re-enter new password for verification: ",
+ new_password,
+ &new_pwsize))) {
+ fprintf(stderr, "Error while reading new password for '%s'",
+ client_name);
+ (void) memset((char *) new_password, 0, ADM_MAX_PW_LENGTH+1);
+ free(new_password);
+ goto finish;
+ }
+ if (new_pwsize == 0) {
+ fprintf(stderr, "A null password is not allowed!\n");
+ free(new_password);
+ goto finish;
+ }
+#endif
+
+ inbuf.data = new_password;
+ inbuf.length = strlen(new_password);
+
+ if ((retval = krb5_mk_priv(context, new_auth_context, &inbuf,
+ &msg_data, &replaydata))) {
+ fprintf(stderr, "Error during Second Message Encoding: %s!\n",
+ error_message(retval));
+ goto finish;
+ }
+ memset(inbuf.data,0,inbuf.length);
+ free(inbuf.data);
+
+ /* write private message to server */
+ if (krb5_write_message(context, &local_socket, &msg_data)){
+ fprintf(stderr, "Write Error During Second Message Transmission!\n");
+ retval = 1;
+ goto finish;
+ }
+ free(msg_data.data);
+
+ /* Ok Now let's get the private message */
+ if (retval = krb5_read_message(context, &local_socket, &inbuf)){
+ fprintf(stderr, "Read Error During Second Reply: %s!\n",
+ error_message(retval));
+ retval = 1;
+ goto finish;
+ }
+
+ if ((retval = krb5_rd_priv(context, new_auth_context, &inbuf,
+ &msg_data, &replaydata))) {
+ fprintf(stderr, "Error during Second Read Decoding :%s!\n",
+ error_message(retval));
+ goto finish;
+ }
+
+ rd_priv_resp.appl_code = msg_data.data[0];
+ rd_priv_resp.oper_code = msg_data.data[1];
+ rd_priv_resp.retn_code = msg_data.data[2];
+ if (msg_data.length > 3 && msg_data.data[3]) {
+ rd_priv_resp.message = (char *)malloc(msg_data.length - 2);
+ if (rd_priv_resp.message) {
+ memcpy(rd_priv_resp.message, msg_data.data + 3,
+ msg_data.length - 3);
+ rd_priv_resp.message[msg_data.length - 3] = 0;
+ }
+ } else
+ rd_priv_resp.message = NULL;
+
+
+ free(inbuf.data);
+ free(msg_data.data);
+ if (rd_priv_resp.appl_code == KPASSWD) {
+ if (rd_priv_resp.retn_code == KPASSGOOD)
+ printf("\n\nPassword changed.\n\n");
+ else if (rd_priv_resp.retn_code == KPASSBAD) {
+ if (rd_priv_resp.message)
+ fprintf(stderr, "%s\n", rd_priv_resp.message);
+ else
+ fprintf(stderr, "Server returned KPASSBAD.\n");
+ } else
+ fprintf(stderr, "Server returned unknown kerberos code.\n");
+ } else
+ fprintf(stderr, "Server returned bad application code %d\n",
+ rd_priv_resp.appl_code);
+
+ if (rd_priv_resp.message)
+ free(rd_priv_resp.message);
+
+ finish:
+
+ (void) krb5_cc_destroy(context, cache);
+
+ free(client_name);
+ free(requested_realm.data);
+
+ if (retval) {
+ fprintf(stderr, "\n\nProtocol Failure - Password NOT changed\n\n");
+ exit(1);
+ }
+
+ printf("\n\nPassword changed.\n\n");
+
+ exit(0);
+}
+
+
+
+krb5_data cpwname = {
+ 0,
+ sizeof(CPWNAME)-1,
+ CPWNAME
+};
+
+static krb5_error_code
+get_first_ticket(context, cache, client, my_creds)
+ krb5_context context;
+ krb5_ccache cache;
+ krb5_principal client;
+ krb5_creds *my_creds;
+{
+ char prompt[255]; /* for the password prompt */
+ char pword[ADM_MAX_PW_LENGTH+1]; /* storage for the password */
+ char *old_password;
+ int old_pwsize;
+ int i;
+
+ krb5_address **my_addresses;
+
+ char *client_name;
+ krb5_error_code retval;
+
+ if ((retval = krb5_unparse_name(context, client, &client_name))) {
+ fprintf(stderr, "Unable to Unparse Client Name\n");
+ return(1);
+ }
+
+ (void) sprintf(prompt,"Old password for %s: ", (char *) client_name);
+
+ if ((retval = krb5_os_localaddr(&my_addresses))) {
+ fprintf(stderr, "Unable to Get Customers Address\n");
+ return(1);
+ }
+
+ memset((char *) my_creds, 0, sizeof(krb5_creds));
+
+ my_creds->client = client;
+
+ if ((retval = krb5_build_principal_ext(context, &my_creds->server,
+ client->realm.length,
+ client->realm.data,
+ cpwname.length, /* 6 */
+ cpwname.data, /* "kadmin" */
+ client->realm.length,
+ /* instance is local realm */
+ client->realm.data,
+ 0))) {
+ fprintf(stderr, "Error %s while building server name\n",
+ error_message(retval));
+ return(1);
+ }
+
+
+ if ((old_password = (char *) calloc (1, 255)) == NULL) {
+ fprintf(stderr, "No Memory for Retrieving old password\n");
+ return(1);
+ }
+
+ old_pwsize = 255;
+ if ((retval = krb5_read_password(context,
+ prompt,
+ 0,
+ old_password,
+ &old_pwsize))) {
+ fprintf(stderr, "Error while reading password for '%s'",
+ client_name);
+ return(1);
+ }
+
+ retval = krb5_get_in_tkt_with_password(context, 0,/* options */
+ my_addresses,
+ NULL, /* Default encryption list */
+ NULL, /* Default preauth list */
+ old_password, cache, my_creds, 0);
+
+ if (retval) {
+ fprintf(stderr, "\nUnable to Get Initial Credentials : %s %d\n",
+ error_message(retval),retval);
+ }
+
+ /* Do NOT Forget to zap password */
+ memset((char *) old_password, 0, old_pwsize);
+ free(old_password);
+ memset((char *) pword, 0, sizeof(pword));
+ return(retval);
+}
+
+#ifdef MACH_PASS /* Machine-generated Passwords */
+krb5_error_code
+print_and_choose_password(new_password, decodable_pwd_string)
+ char * new_password;
+ krb5_data * decodable_pwd_string;
+{
+krb5_error_code retval;
+ krb5_pwd_data *pwd_data;
+ passwd_phrase_element **next_passwd_phrase_element;
+ char prompt[255];
+ int i, j, k;
+ int legit_pswd = 0; /* Assume No Legitimate Password */
+ char *password_list[ADM_MAX_PW_CHOICES];
+ char verification_passwd[ADM_MAX_PW_LENGTH+1];
+ /* char new_passwd[ADM_MAX_PW_LENGTH]; */
+ char phrase_in[ADM_MAX_PHRASE_LENGTH];
+ int new_passwd_length;
+ char *ptr;
+ int verify = 0; /* Do Not Request Password Selection Verification */
+ int ok = 0;
+
+#define free_local_password_list() \
+{ for ( k = 0; k < i && k < ADM_MAX_PW_CHOICES; k++) { \
+ (void) memset(password_list[k], 0, ADM_MAX_PW_LENGTH); \
+ free(password_list[k]); } \
+}
+
+ /* Decode Password and Phrase Information Obtained from krb5_rd_priv */
+ if ((retval = decode_krb5_pwd_data(decodable_pwd_string , &pwd_data))) {
+ fprintf(stderr, "Unable to Decode Passwords and Phrases\n");
+ fprintf(stderr, " Notify your System Administrator or the ");
+ fprintf(stderr, "Kerberos Administrator\n");
+ return(1);
+ }
+
+ next_passwd_phrase_element = pwd_data->element;
+ /* Display List in 5 Password/Phrase Increments up to MAX Iterations */
+ memset((char *) phrase_in, 0, ADM_MAX_PHRASE_LENGTH);
+ for ( j = 0; j <= ADM_MAX_PW_ITERATIONS; j++) {
+ if (j == ADM_MAX_PW_ITERATIONS) {
+ fprintf(stderr, "\n\nSorry - You Have Exceeded the List of ");
+ fprintf(stderr, "Choices (%d) Allowed for Password\n",
+ ADM_MAX_PW_ITERATIONS * ADM_MAX_PW_CHOICES);
+ fprintf(stderr, " Modification. You Must Repeat this ");
+ fprintf(stderr, "Operation in order to Successfully\n");
+ fprintf(stderr, " Change your Password.\n");
+ break;
+ }
+
+ display_print:
+ printf("\n\nChoose a password from the following list:\n");
+
+ printf("\n\nPassword Remembrance Aid\n\n\n");
+
+ /* Print Passwords and Assistance Phrases List */
+ for ( i = 0; i < ADM_MAX_PW_CHOICES; i++){
+ if ((password_list[i] = (char *) calloc (1,
+ ADM_MAX_PW_LENGTH + 1)) == NULL) {
+ fprintf(stderr, "Unable to Allocate Password List.\n");
+ return(1);
+ }
+
+ memcpy(password_list[i],
+ (*next_passwd_phrase_element)->passwd->data,
+ (*next_passwd_phrase_element)->passwd->length);
+ printf("%s ", password_list[i]);
+
+ memcpy((char *) phrase_in,
+ (*next_passwd_phrase_element)->phrase->data,
+ (*next_passwd_phrase_element)->phrase->length);
+ for ( k = 0;
+ k < 50 && k < (*next_passwd_phrase_element)->phrase->length;
+ k++) {
+ printf("%c", phrase_in[k]);
+ }
+ for ( k = k;
+ k < 70 && k < (*next_passwd_phrase_element)->phrase->length;
+ k++) {
+ if (phrase_in[k] == ' ') {
+ printf("\n ");
+ k++;
+ break;
+ } else {
+ printf("%c", phrase_in[k]);
+ }
+ }
+ for ( k = k;
+ k < (*next_passwd_phrase_element)->phrase->length;
+ k++) {
+ printf("%c", phrase_in[k]);
+ }
+ printf("\n\n");
+ memset((char *) phrase_in, 0, ADM_MAX_PHRASE_LENGTH);
+ next_passwd_phrase_element++;
+ }
+
+ sprintf(prompt,
+ "\n\nEnter Password Selection or a <CR> to get new list: ");
+
+ new_passwd_length = ADM_MAX_PW_LENGTH+1;
+ /* Read New Password from Terminal (Do Not Print on Screen) */
+ if ((retval = krb5_read_password(context, &prompt[0], 0,
+ new_password, &new_passwd_length))) {
+ fprintf(stderr,
+ "\nError Reading Password Input or Input Aborted\n");
+ free_local_password_list();
+ break;;
+ }
+
+ /* Check for <CR> ==> Provide a New List */
+ if (new_passwd_length == 0) continue;
+
+ /* Check that Selection is from List - Server also does this */
+ legit_pswd = 0;
+ for (i = 0; i < ADM_MAX_PW_CHOICES && !legit_pswd; i++)
+ if ((retval = memcmp(new_password,
+ password_list[i], 8)) == 0) {
+ legit_pswd++;
+ }
+ free_local_password_list();
+
+ if (!(legit_pswd)) {
+ printf("\n\07\07Password must be from the specified list ");
+ printf("- Try Again!\n");
+ }
+
+ if (legit_pswd) break; /* Exit Loop */
+ } /* ADM_MAX_PW_CHOICES Loop */
+
+ if (!(legit_pswd)) return (1);
+
+ return(0); /* SUCCESS */
+}
+#endif
+
+static krb5_error_code
+adm5_init_link(context, realm_of_server, local_socket)
+ krb5_context context;
+ krb5_data *realm_of_server;
+ int * local_socket;
+{
+ struct servent *service_process; /* service we will talk to */
+ struct hostent *remote_host; /* host we will talk to */
+
+ char **hostlist;
+
+ int host_count;
+ int namelen;
+ int i, count;
+
+ krb5_error_code retval;
+
+ /* clear out the structure first */
+ (void) memset((char *)&remote_sin, 0, sizeof(remote_sin));
+
+ if ((service_process = getservbyname(CPW_SNAME, "tcp")) == NULL) {
+ fprintf(stderr, "Unable to find Service (%s) Check services file\n",
+ CPW_SNAME);
+ return(1);
+ }
+
+ /* Copy the Port Number */
+ remote_sin.sin_port = service_process->s_port;
+
+ hostlist = 0;
+
+ /* Identify all Hosts Associated with this Realm */
+ if ((retval = krb5_get_krbhst (context, realm_of_server, &hostlist))) {
+ fprintf(stderr, "krb5_get_krbhst: Unable to Determine Server Name\n");
+ return(1);
+ }
+
+ for (i=0; hostlist[i]; i++);
+
+ count = i;
+
+ if (count == 0) {
+ host_count = 0;
+ fprintf(stderr, "No hosts found\n");
+ return(1);
+ }
+
+ for (i=0; hostlist[i]; i++) {
+ remote_host = gethostbyname(hostlist[i]);
+ if (remote_host != 0) {
+
+ /* set up the address of the foreign socket for connect() */
+ remote_sin.sin_family = remote_host->h_addrtype;
+ (void) memcpy((char *) &remote_sin.sin_addr,
+ (char *) remote_host->h_addr,
+ sizeof(remote_host->h_addr));
+ break; /* Only Need one */
+ }
+ }
+
+ free ((char *)hostlist);
+
+ /* open a TCP socket */
+ *local_socket = socket(PF_INET, SOCK_STREAM, 0);
+ if (*local_socket < 0) {
+ fprintf(stderr, "Cannot Open Socket\n");
+ return(1);
+ }
+ /* connect to the server */
+ if (connect(*local_socket, &remote_sin, sizeof(remote_sin)) < 0) {
+ fprintf(stderr, "Cannot Connect to Socket\n");
+ close(*local_socket);
+ return(1);
+ }
+
+ /* find out who I am, now that we are connected and therefore bound */
+ namelen = sizeof(local_sin);
+ if (getsockname(*local_socket,
+ (struct sockaddr *) &local_sin, &namelen) < 0) {
+ fprintf(stderr, "Cannot Perform getsockname\n");
+ close(*local_socket);
+ return(1);
+ }
+ return(0);
+}
+
+usage()
+{
+ fprintf(stderr, "Usage: ");
+ fprintf(stderr, "kpasswd [name]\n");
+ exit(0);
+}
--- /dev/null
+/* Networked */
+/* */
+/* Written by: Glenn Machin 2931 */
+/* Originated: Nov 12, 1990 */
+/* Description: */
+/* */
+/* This program/routine exits/returns with a status 1 if */
+/* the terminal associated with the current process is */
+/* connected from a remote host, otherwise exits/returns */
+/* with a value of 0. */
+/* */
+/* This program/routine makes some basic assumptions about */
+/* utmp: */
+/* *The login process, rcmd, or window application */
+/* makes an entry into utmp for all currents */
+/* users. */
+/* *For entries in which the users have logged in */
+/* locally. The line name is not a pseudo tty */
+/* device. */
+/* *For X window application in which */
+/* the device is a pseudo tty device but the */
+/* display is the local system, then the ut_host */
+/* has the format system_name:0.0 or :0.0. */
+/* All other entries will be assumed to be */
+/* networked. */
+/* */
+/* Changes: 11/15/90 Check for file /etc/krb.secure. */
+/* If it exists then perform network */
+/* check, otherwise return 0. */
+/****************************************************************/
+/*
+ * Sandia National Laboratories also makes no representations about the
+ * suitability of the modifications, or additions to this software for
+ * any purpose. It is provided "as is" without express or implied warranty.
+ */
+#include <string.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifndef _TYPES_
+#include <sys/types.h>
+#ifndef _TYPES_
+#define _TYPES_
+#endif
+#endif
+#include <utmp.h>
+#include <pwd.h>
+
+#ifndef MAXHOSTNAME
+#define MAXHOSTNAME 64
+#endif
+
+#ifdef NO_UT_PID
+
+static int utfile;
+
+#include <fcntl.h>
+
+static void kadmin_setutent()
+{
+ utfile = open("/etc/utmp",O_RDONLY);
+}
+
+static struct utmp * kadmin_getutline(utmpent)
+struct utmp *utmpent;
+{
+ static struct utmp tmputmpent;
+ int found = 0;
+ while ( read(utfile,&tmputmpent,sizeof(struct utmp)) > 0 ){
+ if ( strcmp(tmputmpent.ut_line,utmpent->ut_line) == 0){
+#ifdef NO_UT_HOST
+ if ( ( 1) &&
+#else
+ if ( (strcmp(tmputmpent.ut_host,"") == 0) &&
+#endif
+ (strcmp(tmputmpent.ut_name,"") == 0)) continue;
+ found = 1;
+ break;
+ }
+ }
+ if (found)
+ return(&tmputmpent);
+ return((struct utmp *) 0);
+}
+
+static void kadmin_endutent()
+{
+ close(utfile);
+}
+#else
+#define kadmin_setutent setutent
+#define kadmin_getutline getutline
+#define kadmin_endutent endutent
+#endif /* defined(HAVE_GETUTENT) && !defined(NO_UT_PID) */
+
+
+int network_connected()
+{
+struct utmp utmpent;
+struct utmp retutent, *tmpptr;
+char *display_indx;
+char currenthost[MAXHOSTNAME];
+char *username,*tmpname;
+
+
+/* Macro for pseudo_tty */
+#define pseudo_tty(ut) \
+ ((strncmp((ut).ut_line, "tty", 3) == 0 && ((ut).ut_line[3] == 'p' \
+ || (ut).ut_line[3] == 'q' \
+ || (ut).ut_line[3] == 'r' \
+ || (ut).ut_line[3] == 's'))\
+ || (strncmp((ut).ut_line, "pty", 3) == 0))
+
+ /* Check to see if getlogin returns proper name */
+ if ( (tmpname = (char *) getlogin()) == (char *) 0) return(1);
+ username = (char *) malloc(strlen(tmpname) + 1);
+ if ( username == (char *) 0) return(1);
+ strcpy(username,tmpname);
+
+ /* Obtain tty device for controlling tty of current process.*/
+ strncpy(utmpent.ut_line,ttyname(0) + strlen("/dev/"),
+ sizeof(utmpent.ut_line));
+
+ /* See if this device is currently listed in /etc/utmp under
+ calling user */
+#ifndef NO_UT_TYPE
+ utmpent.ut_type = USER_PROCESS;
+#define ut_name ut_user
+#endif
+ kadmin_setutent();
+ while ( (tmpptr = (struct utmp *) kadmin_getutline(&utmpent))
+ != ( struct utmp *) 0) {
+
+ /* If logged out name and host will be empty */
+ if ((strcmp(tmpptr->ut_name,"") == 0) &&
+#ifdef NO_UT_HOST
+ ( 1)) continue;
+#else
+ (strcmp(tmpptr->ut_host,"") == 0)) continue;
+#endif
+ else break;
+ }
+ if ( tmpptr == (struct utmp *) 0) {
+ kadmin_endutent();
+ return(1);
+ }
+ memcpy((char *)&retutent,(char *)tmpptr,sizeof(struct utmp));
+ kadmin_endutent();
+#ifdef DEBUG
+#ifdef NO_UT_HOST
+ printf("User %s on line %s :\n",
+ retutent.ut_name,retutent.ut_line);
+#else
+ printf("User %s on line %s connected from host :%s:\n",
+ retutent.ut_name,retutent.ut_line,retutent.ut_host);
+#endif
+#endif
+ if (strcmp(retutent.ut_name,username) != 0) {
+ return(1);
+ }
+
+
+ /* If this is not a pseudo tty then everything is OK */
+ if (! pseudo_tty(retutent)) return(0);
+
+ /* OK now the work begins there is an entry in utmp and
+ the device is a pseudo tty. */
+
+ /* Check if : is in hostname if so this is xwindow display */
+
+ if (gethostname(currenthost,sizeof(currenthost))) return(1);
+#ifdef NO_UT_HOST
+ display_indx = (char *) 0;
+#else
+ display_indx = (char *) strchr(retutent.ut_host,':');
+#endif
+ if ( display_indx != (char *) 0) {
+ /*
+ We have X window application here. The host field should have
+ the form => local_system_name:0.0 or :0.0
+ if the window is being displayed on the local system.
+ */
+#ifdef NO_UT_HOST
+ return(1);
+#else
+ if (strncmp(currenthost,retutent.ut_host,
+ (display_indx - retutent.ut_host)) != 0) return(1);
+ else return(0);
+#endif
+ }
+
+ /* Host field is empty or is not X window entry. At this point
+ we can't trust that the pseudo tty is not connected to a
+ networked process so let's return 1.
+ */
+ return(1);
+}
+
+#ifdef NOTKERBEROS
+main(argc,argv)
+int argc;
+char **argv;
+{
+ if (network_connected()){
+#ifdef DEBUG
+ printf("Networked\n");
+#endif
+ exit(1);
+ }
+ else {
+#ifdef DEBUG
+ printf("Not networked\n");
+#endif
+ exit(0);
+ }
+}
+#else
+int networked()
+{
+ return(network_connected());
+}
+#endif
--- /dev/null
+# Sanitize.in for Kerberos V5
+
+# Each directory to survive it's way into a release will need a file
+# like this one called "./.Sanitize". All keyword lines must exist,
+# and must exist in the order specified by this file. Each directory
+# in the tree will be processed, top down, in the following order.
+
+# Hash started lines like this one are comments and will be deleted
+# before anything else is done. Blank lines will also be squashed
+# out.
+
+# The lines between the "Do-first:" line and the "Things-to-keep:"
+# line are executed as a /bin/sh shell script before anything else is
+# done in this
+
+Do-first:
+
+# All files listed between the "Things-to-keep:" line and the
+# "Files-to-sed:" line will be kept. All other files will be removed.
+# Directories listed in this section will have their own Sanitize
+# called. Directories not listed will be removed in their entirety
+# with rm -rf.
+
+Things-to-keep:
+
+.cvsignore
+ChangeLog
+Makefile.in
+adm_adm_func.c
+adm_check.c
+adm_extern.c
+adm_extern.h
+adm_fmt_inq.c
+adm_funcs.c
+adm_kadmin.c
+adm_kpasswd.c
+adm_listen.c
+adm_msgs.c
+adm_nego.c
+adm_network.c
+adm_parse.c
+adm_process.c
+adm_server.c
+adm_v4_pwd.c
+admin_acl_file
+configure
+configure.in
+kadmind.M
+
+Things-to-lose:
+
+Do-last:
+
+# End of file.
--- /dev/null
+Fri Apr 21 13:11:00 1995 Mark Eichin <eichin@cygnus.com>
+
+ From Ian Taylor <ian@cygnus.com>. Makes kadmind use -r for both
+ the database name and the service name, eliminating an
+ installation hassle.
+ * adm_extern.h: declare realm.
+ * adm_server.c: define realm.
+ (process_args): change db_realm to realm.
+ * adm_network.c (setup_network): use the preset realm, not the
+ default realm.
+
+Thu Apr 20 18:05:00 1995 Mark Eichin <eichin@cygnus.com>
+
+ Changes from Ian Taylor <ian@cygnus.com> to support testsuite.
+ * adm_extern.h: declare admin_port.
+ * adm_extern.c: define admin_port.
+ * adm_server.c (process_args): set admin_port from -p command line
+ argument.
+ (usage): document -p port option.
+ * adm_network.c (setup_network): use admin_port if set.
+
+Thu Apr 20 11:47:53 1995 <tytso@rsx-11.mit.edu>
+
+ * adm_extern.h: #include adm_defs.h, since that's no longer
+ included by krb5.h
+
+Mon Mar 27 07:56:26 1995 Chris Provenzano (proven@mit.edu)
+
+ * adm_process.c, adm_kadmin.c, adm_adm_func.c, adm_kpasswd.c,
+ * adm_funcs, adm_nego.c adm_extern.c and adm_listen.c
+ Use new calling convention for krb5_recvauth(), krb5_mk_priv(),
+ krb5_rd_priv(), krb5_mk_safe(), and krb5_rd_safe().
+ (Redid many of the internal functions to accomidate new a
+ uth_context structure and remove old unnecessary structures.)
+
+Fri Mar 24 14:38:06 1995 <tytso@rsx-11.mit.edu>
+
+ * adm_network.c (setup_network): If /etc/services doesn't have the
+ administration port, use a compiled in port.
+
+Thu Mar 2 12:24:50 1995 Theodore Y. Ts'o <tytso@dcl>
+
+ * Makefile.in (ISODELIB): Remove reference to $(ISODELIB).
+
+Wed Mar 1 16:29:53 1995 Theodore Y. Ts'o <tytso@dcl>
+
+ * configure.in: Remove ISODE_INCLUDE, replace check for -lsocket
+ and -lnsl with WITH_NETLIB check.
+
+Tue Feb 28 02:23:46 1995 John Gilmore (gnu at toad.com)
+
+ * *.c: Avoid <krb5/...> and <com_err.h> includes.
+
+Fri Feb 3 07:50:14 1995 Theodore Y. Ts'o (tytso@dcl)
+
+ * adm_v4_pwd.c: Don't use BITS64, use SIZEOF_LONG
+
+Wed Feb 01 22:05:35 1995 Chris Provenzano (proven@mit.edu)
+
+ * adm_process.c, adm_extern.h (cpw_keyproc()) Added
+ krb5_keytype arg.
+
+Wed Jan 25 16:54:40 1995 Chris Provenzano (proven@mit.edu)
+
+ * Removed all narrow types and references to wide.h and narrow.h
+
+Wed Jan 18 10:26:30 1995 <tytso@rsx-11.mit.edu>
+
+ * adm_server.c (process_args): Modify getopt args so that the 'M'
+ option takes an argument. (krb5 bugs 984)
+
+Fri Jan 13 15:23:47 1995 Chris Provenzano (proven@mit.edu)
+
+ * Added krb5_context to all krb5_routines
+
+Mon Dec 19 18:12:18 1994 Theodore Y. Ts'o (tytso@dcl)
+
+ * adm_listen.c (kill_children): Use syslog instead of krb_log.
+
+Tue Nov 1 18:19:36 1994 Mark Eichin (eichin@cygnus.com)
+
+ * adm_listen.c (kill_children): use sigprocmask if available.
+
+Wed Oct 19 17:40:22 1994 Theodore Y. Ts'o (tytso@dcl)
+
+ * adm_server.c (main): Select the cryptosystem to be used using
+ krb5_use_cstype() instead of using a implementation
+ specific assignment. Also, allow the encryption type to
+ be specified using a command line option.
+
+Tue Oct 4 17:08:25 1994 Theodore Y. Ts'o (tytso@dcl)
+
+ * adm_process.c (cpw_keyproc): Add widen.h and narrow.h around
+ declaration so that argument types to keyproc are widened.
+
+Mon Oct 3 19:13:03 1994 Theodore Y. Ts'o (tytso@dcl)
+
+ * Makefile.in: Use $(srcdir) to find manual page for make install.
+
+Thu Sep 29 22:41:08 1994 Theodore Y. Ts'o (tytso@dcl)
+
+ * Makefile.in: relink executable if libraries change
+
+Wed Sep 14 22:33:23 1994 Theodore Y. Ts'o (tytso@dcl)
+
+ * adm_server (init_db): Save a copy of the master key database
+ entry in the master_entry global variable.
+
+ * adm_process.c (process_client): Removed calls to
+ free(final_msg.data), where final_msg.data was pointing to
+ an automatic variable.
+
+ * adm_process.c (cpw_keyproc): In the case where the
+ keyprocarg->key is set, copy the keyblock instead of
+ passing a pointer down --- more pointer aliasing problems!
+
+ * adm_funcs.c (adm_modify_kdb): Added calls to krb5_copy_principal
+ instead of merely assigning pointers to one another and
+ causing pointer aliasing problems. Make sure the master
+ key version number is propagated correctly.
+
+Thu Aug 4 03:38:58 1994 Tom Yu (tlyu@dragons-lair)
+
+ * Makefile.in: whoops install manpage as kadmin.8, not kadmin.1
+
+ * Makefile.in: install kadmind in the right place
+
+Sat Jul 16 09:22:19 1994 Tom Yu (tlyu at dragons-lair)
+
+ * configure.in: another attempt to make dbm libs dtrt
+
+Fri Jul 1 16:01:02 1994 Mark Eichin (eichin@cygnus.com)
+
+ * adm_listen.c: if USE_SIGPROCMASK, replace sigblock et al.
+ configure.in: CHECK_SIGPROCMASK.
+
+Wed Jun 29 00:25:29 1994 Tom Yu (tlyu at dragons-lair)
+
+ * adm_server.c: fixed error table calls to use krb5_init_ets
+
+Fri Jun 24 20:39:37 1994 Theodore Y. Ts'o (tytso at tsx-11)
+
+ * adm_process.c (cpw_keyproc): return error codes on failure
+
+ * adm_nego.c (adm_negotiate_key): added return on memory
+ allocation error
+
+ * adm_fmt_inq.c (adm_fmt_prt, adm_print_exp_time,
+ adm_print_attributes): Sanitized error return strategies.
+
+ * adm_kadmin.c (adm5_kadmin): Plug memory leaks, fix double
+ free's, fix message in error syslog.
+
+ * adm_process.c (process_client): Plug memory leaks
+
+ * adm_adm_func. (adm_inq_old_key): Plug memory leaks, return error
+ when adm_fmt_prt returns an error
+
+ * adm_adm_func.c (adm_mod_old_key): Plug memory leaks, report error
+ if put_principal returns an error.
+
+ * adm_adm_func.c (adm_change_pwd_rnd): Fix syslog information
+
+ * adm_adm_func.c (adm_build_key): Plug memory leak
+
+
--- /dev/null
+CFLAGS = $(CCOPTS) $(DEFS) $(LOCALINCLUDE)
+LDFLAGS = -g
+
+COMERRLIB=$(BUILDTOP)/util/et/libcom_err.a
+SSLIB=$(BUILDTOP)/util/ss/libss.a
+DBMLIB=
+KDBLIB=$(TOPLIBD)/libkdb5.a
+DEPKDBLIB=$(TOPLIBD)/libkdb5.a
+
+all::
+
+KLIB = $(TOPLIBD)/libkrb5.a $(TOPLIBD)/libcrypto.a $(SSLIB) $(COMERRLIB) $(DBMLIB)
+DEPKLIB = $(TOPLIBD)/libkrb5.a $(TOPLIBD)/libcrypto.a $(SSLIB) $(COMERRLIB) $(DBMLIB)
+
+DEPLIBS = $(DEPKDBLIB) $(DEPKLIB)
+LOCAL_LIBRARIES = $(KDBLIB) $(KLIB)
+
+
+SRCS = \
+ $(srcdir)/adm_server.c \
+ $(srcdir)/adm_parse.c \
+ $(srcdir)/adm_network.c \
+ $(srcdir)/adm_listen.c \
+ $(srcdir)/adm_process.c \
+ $(srcdir)/adm_nego.c \
+ $(srcdir)/adm_kpasswd.c \
+ $(srcdir)/adm_kadmin.c \
+ $(srcdir)/adm_fmt_inq.c \
+ $(srcdir)/adm_adm_func.c \
+ $(srcdir)/adm_funcs.c \
+ $(srcdir)/adm_check.c \
+ $(srcdir)/adm_extern.c \
+ $(srcdir)/adm_msgs.c
+
+OBJS = \
+ adm_server.o \
+ adm_parse.o \
+ adm_network.o \
+ adm_listen.o \
+ adm_process.o \
+ adm_nego.o \
+ adm_kpasswd.o \
+ adm_kadmin.o \
+ adm_fmt_inq.o \
+ adm_adm_func.o \
+ adm_funcs.o \
+ adm_check.o \
+ adm_extern.o \
+ adm_msgs.o
+
+all:: kadmind
+
+kadmind: $(KDBDEPLIB) $(OBJS) $(DEPLIBS)
+ $(CC) $(CFLAGS) -o kadmind $(OBJS) $(KDBLIB) $(K4LIB) $(KLIB) $(LIBS)
+
+install::
+ $(INSTALL_PROGRAM) kadmind ${DESTDIR}$(SERVER_BINDIR)/kadmind
+ $(INSTALL_DATA) $(srcdir)/kadmind.M ${DESTDIR}$(SERVER_MANDIR)/kadmind.8
+
+clean::
+ $(RM) kadmind
+
--- /dev/null
+/*
+ * kadmin/server/adm_adm_func.c
+ *
+ * Copyright 1990,1991 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * 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. 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.
+ *
+ * Sandia National Laboratories also makes no representations about the
+ * suitability of the modifications, or additions to this software for
+ * any purpose. It is provided "as is" without express or implied warranty.
+ *
+ * Modify the Kerberos Database
+ */
+
+
+#include <sys/types.h>
+#include <syslog.h>
+#include "com_err.h"
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#ifndef hpux
+#include <arpa/inet.h>
+#endif
+
+#include "k5-int.h"
+#include "adm_extern.h"
+
+#ifdef SANDIA
+extern int classification;
+#endif
+
+krb5_error_code
+adm_build_key (context, auth_context, new_passwd, oper_type, entry)
+ krb5_context context;
+ krb5_auth_context * auth_context;
+ char *new_passwd;
+ int oper_type;
+ krb5_db_entry entry;
+{
+ krb5_replay_data replaydata;
+ krb5_data outbuf;
+ int retval;
+#if defined(MACH_PASS) || defined(SANDIA)
+ char *tmp_phrase;
+ char *tmp_passwd;
+ int pwd_length, phrase_length;
+#endif
+
+#if defined(MACH_PASS) || defined(SANDIA)
+
+ if ((tmp_passwd = (char *) calloc (1, 120)) == (char *) 0) {
+ com_err("adm_build_key", ENOMEM, "for tmp_passwd");
+ return(3); /* No Memory */
+ }
+
+ if ((tmp_phrase = (char *) calloc (1, 120)) == (char *) 0) {
+ free(tmp_passwd);
+ com_err("adm_build_key", ENOMEM, "for tmp_phrase");
+ return(3); /* No Memory */
+ }
+
+ if (retval = get_pwd_and_phrase("adm_build_key", &tmp_passwd,
+ &tmp_phrase)) {
+ free(tmp_passwd);
+ free(tmp_phrase);
+ return(4); /* Unable to get Password */
+ }
+
+ if ((outbuf.data = (char *) calloc (1, strlen(tmp_passwd) + 1)) ==
+ (char *) 0) {
+ com_err("adm_build_key", ENOMEM, "for outbuf.data");
+ free(tmp_passwd);
+ free(tmp_phrase);
+ return(3); /* No Memory */
+ }
+
+ outbuf.length = strlen(tmp_passwd);
+ (void) memcpy(outbuf.data, tmp_passwd, strlen(tmp_passwd));
+
+#else
+
+ if ((outbuf.data = (char *) calloc (1, 3)) ==
+ (char *) 0) {
+ com_err("adm_build_key", ENOMEM, "for outbuf.data");
+ return(3); /* No Memory */
+ }
+
+ outbuf.data[0] = KADMIN;
+ outbuf.data[1] = oper_type;
+ outbuf.data[2] = KADMGOOD;
+ outbuf.length = 3;
+
+ if (oper_type == CHGOPER || oper_type == CH4OPER) {
+ outbuf.data[3] = entry.salt_type;
+ outbuf.length = 4;
+ }
+
+#endif
+
+ /* Encrypt Password and Phrase */
+ if (retval = krb5_mk_priv(context, auth_context, &outbuf,
+ &msg_data, &replaydata)) {
+ com_err("adm_build_key", retval, "during mk_priv");
+#if defined(MACH_PASS) || defined(SANDIA)
+ free(tmp_passwd);
+ free(tmp_phrase);
+#endif
+ free(outbuf.data);
+ return(5); /* Protocol Failure */
+ }
+
+#if defined(MACH_PASS) || defined(SANDIA)
+ (void) memcpy(new_passwd, tmp_passwd, strlen(tmp_passwd));
+ new_passwd[strlen(tmp_passwd)] = '\0';
+
+ free(tmp_phrase);
+ free(tmp_passwd);
+#endif
+ free(outbuf.data);
+
+ /* Send private message to Client */
+ if (krb5_write_message(context, &client_server_info.client_socket,
+ &msg_data)){
+ free(msg_data.data);
+ com_err("adm_build_key", 0, "Error Performing Password Write");
+ return(5); /* Protocol Failure */
+ }
+
+ free(msg_data.data);
+
+ /* Read Client Response */
+ if (krb5_read_message(context, &client_server_info.client_socket, &inbuf)){
+ syslog(LOG_ERR | LOG_INFO, "Error Performing Password Read");
+ return(5); /* Protocol Failure */
+ }
+
+ /* Decrypt Client Response */
+ if (retval = krb5_rd_priv(context, auth_context, &inbuf,
+ &msg_data, &replaydata)) {
+ syslog(LOG_ERR | LOG_INFO, "adm_build_key krb5_rd_priv error");
+ free(inbuf.data);
+ return(5); /* Protocol Failure */
+ }
+ free(inbuf.data);
+
+#if !defined(MACH_PASS) && !defined(SANDIA)
+ memcpy(new_passwd, msg_data.data, msg_data.length);
+#endif
+
+ free(msg_data.data);
+ return(0);
+}
+
+/* kadmin change password request */
+krb5_error_code
+adm_change_pwd(context, auth_context, prog, customer_name, salttype)
+ krb5_context context;
+ krb5_auth_context * auth_context;
+ char *prog;
+ char *customer_name;
+ int salttype;
+{
+ krb5_db_entry entry;
+ int nprincs = 1;
+
+ krb5_error_code retval;
+ krb5_principal newprinc;
+ char *composite_name;
+ char *new_passwd;
+ int oper_type;
+
+ syslog(LOG_AUTH | LOG_INFO,
+ "Remote Administrative Password Change Request for %s by %s",
+ customer_name, client_server_info.name_of_client);
+
+ if (retval = krb5_parse_name(context, customer_name, &newprinc)) {
+ syslog(LOG_ERR | LOG_INFO, "parse failure while parsing '%s'",
+ customer_name);
+ return(5); /* Protocol Failure */
+ }
+
+ if (!(adm_princ_exists(context, "adm_change_pwd", newprinc,
+ &entry, &nprincs))) {
+ com_err("adm_change_pwd", 0, "Principal does not exist!");
+ krb5_free_principal(context, newprinc);
+ krb5_db_free_principal(context, &entry, nprincs);
+ return(1); /* Principal Unknown */
+ }
+
+ if ((new_passwd = (char *) calloc (1, ADM_MAX_PW_LENGTH+1)) == (char *) 0) {
+ com_err("adm_change_pwd", ENOMEM, "while allocating new_passwd!");
+ krb5_free_principal(context, newprinc);
+ krb5_db_free_principal(context, &entry, nprincs);
+ return(3); /* No Memory */
+ }
+
+ oper_type = (salttype == KRB5_KDB_SALTTYPE_NORMAL) ? CHGOPER : CH4OPER;
+
+ if (retval = adm_build_key(context, auth_context, new_passwd,
+ oper_type, entry)) {
+ krb5_free_principal(context, newprinc);
+ krb5_db_free_principal(context, &entry, nprincs);
+ free(new_passwd);
+ return(retval);
+ }
+
+ retval = krb5_unparse_name(context, newprinc, &composite_name);
+
+ entry.salt_type = (krb5_int32) salttype;
+
+ if (retval = adm_enter_pwd_key(context, "adm_change_pwd",
+ composite_name,
+ newprinc,
+ newprinc,
+ 1, /* chg_entry */
+ salttype,
+ new_passwd,
+ &entry)) retval = 8;
+ krb5_free_principal(context, newprinc);
+ krb5_db_free_principal(context, &entry, nprincs);
+ free(composite_name);
+
+ (void) memset(new_passwd, 0, strlen(new_passwd));
+ free(new_passwd);
+ return(0);
+}
+
+/* kadmin add new random key function */
+krb5_error_code
+adm_change_pwd_rnd(context, cmdname, customer_name)
+ krb5_context context;
+ char *cmdname;
+ char *customer_name;
+{
+ krb5_db_entry entry;
+ int nprincs = 1;
+ krb5_error_code retval;
+ krb5_principal newprinc;
+
+
+ syslog(LOG_AUTH | LOG_INFO,
+ "Remote Administrative Random Password Change Request for %s by %s",
+ customer_name, client_server_info.name_of_client);
+
+ if (retval = krb5_parse_name(context, customer_name, &newprinc)) {
+ com_err("adm_change_pwd_rnd", retval, "while parsing '%s'", customer_name);
+ return(5); /* Protocol Failure */
+ }
+#ifdef SANDIA
+ if (!(newprinc[2])) {
+ if (retval = check_security(newprinc, classification)) {
+ krb5_free_principal(context, newprinc);
+ syslog(LOG_ERR, "Principal (%s) - Incorrect Classification level",
+ customer_name);
+ return(6);
+ }
+ }
+#endif
+ if (!(adm_princ_exists(context, "adm_change_pwd_rnd", newprinc,
+ &entry, &nprincs))) {
+ com_err("adm_change_pwd_rnd", 0, "Principal does not exist!");
+ krb5_free_principal(context, newprinc);
+ krb5_db_free_principal(context, &entry, nprincs);
+ return(1); /* Principal Unknown */
+ }
+
+ if (retval = adm_enter_rnd_pwd_key(context, "adm_change_pwd_rnd",
+ newprinc,
+ 1, /* change existing entry */
+ &entry))
+ retval = 8;
+
+ krb5_free_principal(context, newprinc);
+ krb5_db_free_principal(context, &entry, nprincs);
+ return(retval);
+}
+
+/* kadmin add new key function */
+krb5_error_code
+adm_add_new_key(context, auth_context, cmdname, customer_name, salttype)
+ krb5_context context;
+ krb5_auth_context *auth_context;
+ char *cmdname;
+ char *customer_name;
+ int salttype;
+{
+ krb5_db_entry entry;
+ int nprincs = 1;
+
+ krb5_error_code retval;
+ krb5_principal newprinc;
+ char *new_passwd;
+
+ syslog(LOG_AUTH | LOG_INFO,
+ "Remote Administrative Addition Request for %s by %s",
+ customer_name, client_server_info.name_of_client);
+
+ if (retval = krb5_parse_name(context, customer_name, &newprinc)) {
+ com_err("adm_add_new_key", retval, "while parsing '%s'", customer_name);
+ return(5); /* Protocol Failure */
+ }
+#ifdef SANDIA
+ if (!(newprinc[2])) {
+ if (retval = check_security(newprinc, classification)) {
+ krb5_free_principal(context, newprinc);
+ syslog(LOG_ERR, "Principal (%s) - Incorrect Classification level",
+ customer_name);
+ return(6);
+ }
+ }
+#endif
+ if (adm_princ_exists(context, "adm_add_new_key",newprinc,&entry,&nprincs)) {
+ com_err("adm_add_new_key", 0,
+ "principal '%s' already exists", customer_name);
+ krb5_free_principal(context, newprinc);
+ krb5_db_free_principal(context, &entry, nprincs);
+ return(2); /* Principal Already Exists */
+ }
+
+ if ((new_passwd = (char *) calloc (1, 255)) == (char *) 0) {
+ com_err("adm_add_new_key", ENOMEM, "for new_passwd");
+ krb5_free_principal(context, newprinc);
+ krb5_db_free_principal(context, &entry, nprincs);
+ return(3); /* No Memory */
+ }
+
+ if (retval = adm_build_key(context, auth_context, new_passwd,
+ ADDOPER, entry)) {
+ krb5_free_principal(context, newprinc);
+ krb5_db_free_principal(context, &entry, nprincs);
+ free(new_passwd);
+ return(retval);
+ }
+
+ if (retval = adm_enter_pwd_key(context, "adm_add_new_key",
+ customer_name,
+ newprinc,
+ newprinc,
+ 0, /* new_entry */
+ salttype,
+ new_passwd,
+ &entry))
+ retval = 8;
+ (void) memset(new_passwd, 0, strlen(new_passwd));
+ free(new_passwd);
+ krb5_free_principal(context, newprinc);
+ krb5_db_free_principal(context, &entry, nprincs);
+ return(retval);
+}
+
+/* kadmin add new random key function */
+krb5_error_code
+adm_add_new_key_rnd(context, cmdname, customer_name)
+ krb5_context context;
+ char *cmdname;
+ char *customer_name;
+{
+ krb5_db_entry entry;
+ int nprincs = 1;
+ krb5_error_code retval;
+ krb5_principal newprinc;
+
+
+ syslog(LOG_AUTH | LOG_INFO,
+ "Remote Administrative Addition Request for %s by %s",
+ customer_name, client_server_info.name_of_client);
+
+ if (retval = krb5_parse_name(context, customer_name, &newprinc)) {
+ com_err("adm_add_new_key_rnd", retval, "while parsing '%s'", customer_name);
+ return(5); /* Protocol Failure */
+ }
+#ifdef SANDIA
+ if (!(newprinc[2])) {
+ if (retval = check_security(newprinc, classification)) {
+ krb5_free_principal(context, newprinc);
+ syslog(LOG_ERR, "Principal (%s) - Incorrect Classification level",
+ customer_name);
+ return(6);
+ }
+ }
+#endif
+ if (adm_princ_exists(context, "adm_add_new_key_rnd", newprinc,
+ &entry, &nprincs)) {
+ com_err("adm_add_new_key_rnd", 0,
+ "principal '%s' already exists", customer_name);
+ krb5_free_principal(context, newprinc);
+ krb5_db_free_principal(context, &entry, nprincs);
+ return(2); /* Principal Already Exists */
+ }
+
+ if (retval = adm_enter_rnd_pwd_key(context, "adm_add_new_key_rnd",
+ newprinc,
+ 0, /* new entry */
+ &entry))
+ retval = 8;
+
+ krb5_free_principal(context, newprinc);
+ krb5_db_free_principal(context, &entry, nprincs);
+ return(retval);
+}
+
+/* kadmin delete old key function */
+krb5_error_code
+adm_del_old_key(context, cmdname, customer_name)
+ krb5_context context;
+ char *cmdname;
+ char *customer_name;
+{
+ krb5_db_entry entry;
+ int nprincs = 1;
+
+ krb5_error_code retval;
+ krb5_principal newprinc;
+ int one = 1;
+
+ syslog(LOG_AUTH | LOG_INFO,
+ "Remote Administrative Deletion Request for %s by %s",
+ customer_name, client_server_info.name_of_client);
+
+ if (retval = krb5_parse_name(context, customer_name, &newprinc)) {
+ com_err("adm_del_old_key", retval, "while parsing '%s'", customer_name);
+ return(5); /* Protocol Failure */
+ }
+
+ if (!adm_princ_exists(context, "adm_del_old_key", newprinc,
+ &entry, &nprincs)) {
+ com_err("adm_del_old_key", 0, "principal '%s' is not in the database",
+ customer_name);
+ krb5_free_principal(context, newprinc);
+ krb5_db_free_principal(context, &entry, nprincs);
+ return(1);
+ }
+
+ if (retval = krb5_db_delete_principal(context, newprinc, &one)) {
+ com_err("adm_del_old_key", retval,
+ "while deleting '%s'", customer_name);
+ krb5_free_principal(context, newprinc);
+ krb5_db_free_principal(context, &entry, nprincs);
+ return(8);
+ } else if (one != 1) {
+ com_err("adm_del_old_key", 0,
+ "no principal deleted - unknown error");
+ krb5_free_principal(context, newprinc);
+ krb5_db_free_principal(context, &entry, nprincs);
+ return(8);
+ }
+
+ krb5_free_principal(context, newprinc);
+ krb5_db_free_principal(context, &entry, nprincs);
+ return(0);
+}
+
+/* kadmin modify existing Principal function */
+krb5_error_code
+adm_mod_old_key(context, auth_context, cmdname, customer_name)
+ krb5_context context;
+ krb5_auth_context * auth_context;
+ char *cmdname;
+ char *customer_name;
+{
+ krb5_replay_data replaydata;
+ krb5_db_entry entry;
+ int nprincs = 1;
+ extern int errno;
+
+ krb5_error_code retval;
+ krb5_principal newprinc;
+
+ krb5_data outbuf;
+ char tempstr[20];
+
+ int one = 1;
+
+ syslog(LOG_AUTH | LOG_INFO,
+ "Remote Administrative Modification Request for %s by %s",
+ customer_name, client_server_info.name_of_client);
+
+ if (retval = krb5_parse_name(context, customer_name, &newprinc)) {
+ com_err("adm_mod_old_key", retval, "while parsing '%s'", customer_name);
+ return(5); /* Protocol Failure */
+ }
+
+ for ( ; ; ) {
+
+ if (!adm_princ_exists(context, "adm_mod_old_key", newprinc,
+ &entry, &nprincs)) {
+ krb5_db_free_principal(context, &entry, nprincs);
+ com_err("adm_mod_old_key", 0,
+ "principal '%s' is not in the database",
+ customer_name);
+ krb5_free_principal(context, newprinc);
+ return(1);
+ }
+
+ /* Send Acknowledgement */
+ if ((outbuf.data = (char *) calloc (1, 255)) == (char *) 0) {
+ krb5_free_principal(context, newprinc);
+ krb5_db_free_principal(context, &entry, nprincs);
+ com_err("adm_mod_old_key", ENOMEM, "for outbuf.data");
+ return(3); /* No Memory */
+ }
+
+ outbuf.length = 3;
+ outbuf.data[0] = KADMIND;
+ outbuf.data[1] = MODOPER;
+ outbuf.data[2] = SENDDATA3;
+
+ if (retval = krb5_mk_priv(context, auth_context, &outbuf,
+ &msg_data, &replaydata)) {
+ krb5_free_principal(context, newprinc);
+ krb5_db_free_principal(context, &entry, nprincs);
+ com_err("adm_mod_old_key", retval, "during mk_priv");
+ free(outbuf.data);
+ return(5); /* Protocol Failure */
+ }
+ free(outbuf.data);
+
+ if (krb5_write_message(context, &client_server_info.client_socket,
+ &msg_data)){
+ free(msg_data.data);
+ krb5_free_principal(context, newprinc);
+ krb5_db_free_principal(context, &entry, nprincs);
+ com_err("adm_mod_old_key", 0,
+ "Error Performing Modification Write");
+ return(5); /* Protocol Failure */
+ }
+ free(msg_data.data);
+
+ /* Read Client Response */
+ if (krb5_read_message(context, &client_server_info.client_socket, &inbuf)){
+ krb5_free_principal(context, newprinc);
+ krb5_db_free_principal(context, &entry, nprincs);
+ com_err("adm_mod_old_key", errno,
+ "Error Performing Modification Read");
+ return(5); /* Protocol Failure */
+ }
+
+ /* Decrypt Client Response */
+ if (retval = krb5_rd_priv(context, auth_context, &inbuf,
+ &msg_data, &replaydata)) {
+ com_err("adm_mod_old_key", retval, "krb5_rd_priv error %s",
+ error_message(retval));
+ free(inbuf.data);
+ krb5_free_principal(context, newprinc);
+ krb5_db_free_principal(context, &entry, nprincs);
+ return(5); /* Protocol Failure */
+ }
+
+ free(inbuf.data);
+
+ if (msg_data.data[1] == KADMGOOD) break;
+
+ /* Decode Message - Modify Database */
+ if (msg_data.data[2] != SENDDATA3) {
+ free(msg_data.data);
+ krb5_free_principal(context, newprinc);
+ krb5_db_free_principal(context, &entry, nprincs);
+ return(5); /* Protocol Failure */
+ }
+#ifdef SANDIA
+ if (msg_data.data[3] == KMODFCNT) {
+ (void) memcpy(tempstr, (char *) msg_data.data + 4,
+ msg_data.length - 4);
+ entry.fail_auth_count = atoi(tempstr);
+ }
+#endif
+ if (msg_data.data[3] == KMODVNO) {
+ (void) memcpy(tempstr, (char *) msg_data.data + 4,
+ msg_data.length - 4);
+ entry.kvno = atoi(tempstr);
+ }
+
+ if (msg_data.data[3] == KMODATTR) {
+ if (msg_data.data[4] == ATTRPOST)
+ entry.attributes &= ~KRB5_KDB_DISALLOW_POSTDATED;
+ if (msg_data.data[4] == ATTRNOPOST)
+ entry.attributes |= KRB5_KDB_DISALLOW_POSTDATED;
+ if (msg_data.data[4] == ATTRFOR)
+ entry.attributes &= ~KRB5_KDB_DISALLOW_FORWARDABLE;
+ if (msg_data.data[4] == ATTRNOFOR)
+ entry.attributes |= KRB5_KDB_DISALLOW_FORWARDABLE;
+ if (msg_data.data[4] == ATTRTGT)
+ entry.attributes &= ~KRB5_KDB_DISALLOW_TGT_BASED;
+ if (msg_data.data[4] == ATTRNOTGT)
+ entry.attributes |= KRB5_KDB_DISALLOW_TGT_BASED;
+ if (msg_data.data[4] == ATTRREN)
+ entry.attributes &= ~KRB5_KDB_DISALLOW_RENEWABLE;
+ if (msg_data.data[4] == ATTRNOREN)
+ entry.attributes |= KRB5_KDB_DISALLOW_RENEWABLE;
+ if (msg_data.data[4] == ATTRPROXY)
+ entry.attributes &= ~KRB5_KDB_DISALLOW_PROXIABLE;
+ if (msg_data.data[4] == ATTRNOPROXY)
+ entry.attributes |= KRB5_KDB_DISALLOW_PROXIABLE;
+ if (msg_data.data[4] == ATTRDSKEY)
+ entry.attributes &= ~KRB5_KDB_DISALLOW_DUP_SKEY;
+ if (msg_data.data[4] == ATTRNODSKEY)
+ entry.attributes |= KRB5_KDB_DISALLOW_DUP_SKEY;
+ if (msg_data.data[4] == ATTRLOCK)
+ entry.attributes |= KRB5_KDB_DISALLOW_ALL_TIX;
+ if (msg_data.data[4] == ATTRUNLOCK)
+ entry.attributes &= ~KRB5_KDB_DISALLOW_ALL_TIX;
+ if (msg_data.data[4] == ATTRNOSVR)
+ entry.attributes |= KRB5_KDB_DISALLOW_SVR;
+ if (msg_data.data[4] == ATTRSVR)
+ entry.attributes &= ~KRB5_KDB_DISALLOW_SVR;
+#ifdef SANDIA
+ if (msg_data.data[4] == ATTRPRE)
+ entry.attributes &= ~KRB5_KDB_REQUIRES_PRE_AUTH;
+ if (msg_data.data[4] == ATTRNOPRE)
+ entry.attributes |= KRB5_KDB_REQUIRES_PRE_AUTH;
+ if (msg_data.data[4] == ATTRPWOK)
+ entry.attributes &= ~KRB5_KDB_REQUIRES_PWCHANGE;
+ if (msg_data.data[4] == ATTRPWCHG)
+ entry.attributes |= KRB5_KDB_REQUIRES_PWCHANGE;
+ if (msg_data.data[4] == ATTRSID)
+ entry.attributes &= ~KRB5_KDB_REQUIRES_SECUREID;
+ if (msg_data.data[4] == ATTRNOSID)
+ entry.attributes |= KRB5_KDB_REQUIRES_SECUREID;
+#endif
+ }
+
+ free(msg_data.data);
+ entry.mod_name = client_server_info.client;
+ if (retval = krb5_timeofday(context, &entry.mod_date)) {
+ com_err("adm_mod_old_key", retval, "while fetching date");
+ krb5_free_principal(context, newprinc);
+ krb5_db_free_principal(context, &entry, nprincs);
+ return(5); /* Protocol Failure */
+ }
+
+ retval = krb5_db_put_principal(context, &entry, &one);
+ if (retval) {
+ com_err("adm_mod_old_key", retval, "while storing principal");
+ krb5_free_principal(context, newprinc);
+ krb5_db_free_principal(context, &entry, nprincs);
+ return(8); /* Update failed */
+ }
+ one = 1;
+ } /* for */
+
+ krb5_db_free_principal(context, &entry, nprincs);
+ krb5_free_principal(context, newprinc);
+
+ /* Read Client Response */
+ if (krb5_read_message(context, &client_server_info.client_socket, &inbuf)){
+ com_err("adm_mod_old_key", errno, "Error Performing Read");
+ return(5); /* Protocol Failure */
+ }
+
+ /* Decrypt Client Response */
+ if (retval = krb5_rd_priv(context, auth_context, &inbuf,
+ &msg_data, &replaydata)) {
+ com_err("adm_mod_old_key", retval, "krb5_rd_priv error %s",
+ error_message(retval));
+ free(inbuf.data);
+ return(5); /* Protocol Failure */
+ }
+
+ free(msg_data.data);
+ free(inbuf.data);
+
+ return(0);
+}
+
+/* kadmin inquire existing Principal function */
+krb5_error_code
+adm_inq_old_key(context, auth_context, cmdname, customer_name)
+ krb5_context context;
+ krb5_auth_context * auth_context;
+ char *cmdname;
+ char *customer_name;
+{
+ krb5_replay_data replaydata;
+ krb5_db_entry entry;
+ int nprincs = 1;
+
+ krb5_data outbuf;
+ krb5_error_code retval;
+ krb5_principal newprinc;
+ char *fullname;
+
+ syslog(LOG_AUTH | LOG_INFO,
+ "Remote Administrative Inquiry Request for %s by %s",
+ customer_name, client_server_info.name_of_client);
+
+ if (retval = krb5_parse_name(context, customer_name, &newprinc)) {
+ com_err("adm_inq_old_key", retval, "while parsing '%s'", customer_name);
+ return(5); /* Protocol Failure */
+ }
+
+ if (retval = krb5_unparse_name(context, newprinc, &fullname)) {
+ krb5_free_principal(context, newprinc);
+ com_err("adm_inq_old_key", retval, "while unparsing");
+ return(5); /* Protocol Failure */
+ }
+
+ if (!adm_princ_exists(context, "adm_inq_old_key", newprinc,
+ &entry, &nprincs)) {
+ krb5_db_free_principal(context, &entry, nprincs);
+ krb5_free_principal(context, newprinc);
+ free(fullname);
+ com_err("adm_inq_old_key", 0, "principal '%s' is not in the database",
+ customer_name);
+ return(1);
+ }
+
+ if ((outbuf.data = (char *) calloc (1, 2048)) == (char *) 0) {
+ krb5_db_free_principal(context, &entry, nprincs);
+ krb5_free_principal(context, newprinc);
+ free(fullname);
+ com_err("adm_inq_old_key", ENOMEM, "for outbuf.data");
+ return(3); /* No Memory */
+ }
+
+ /* Format Inquiry Data */
+ if ((retval = adm_fmt_prt(context, &entry, fullname, outbuf.data))) {
+ krb5_db_free_principal(context, &entry, nprincs);
+ krb5_free_principal(context, newprinc);
+ free(fullname);
+ com_err("adm_inq_old_key", 0, "Unable to Format Inquiry Data");
+ return(5); /* XXX protocol failure --- not right, but.. */
+ }
+ outbuf.length = strlen(outbuf.data);
+ krb5_db_free_principal(context, &entry, nprincs);
+ krb5_free_principal(context, newprinc);
+ free(fullname);
+
+ /* Encrypt Inquiry Data */
+ if (retval = krb5_mk_priv(context, auth_context, &outbuf,
+ &msg_data, &replaydata)) {
+ com_err("adm_inq_old_key", retval, "during mk_priv");
+ free(outbuf.data);
+ return(5); /* Protocol Failure */
+ }
+ free(outbuf.data);
+
+ /* Send Inquiry Information */
+ if (krb5_write_message(context, &client_server_info.client_socket,
+ &msg_data)){
+ free(msg_data.data);
+ com_err("adm_inq_old_key", 0, "Error Performing Write");
+ return(5); /* Protocol Failure */
+ }
+
+ free(msg_data.data);
+
+ /* Read Client Response */
+ if (krb5_read_message(context, &client_server_info.client_socket, &inbuf)){
+ com_err("adm_inq_old_key", errno, "Error Performing Read");
+ syslog(LOG_ERR, "adm_inq sock %d", client_server_info.client_socket);
+ return(5); /* Protocol Failure */
+ }
+
+ /* Decrypt Client Response */
+ if (retval = krb5_rd_priv(context, auth_context, &inbuf,
+ &msg_data, &replaydata)) {
+ com_err("adm_inq_old_key", retval, "krb5_rd_priv error %s",
+ error_message(retval));
+ free(inbuf.data);
+ return(5); /* Protocol Failure */
+ }
+
+ /* XXX Decrypt client response.... and we don't use it?!? */
+
+ free(msg_data.data);
+ free(inbuf.data);
+ return(retval);
+}
+
+#ifdef SANDIA
+krb5_error_code
+ check_security(princ, class)
+krb5_principal princ;
+int class;
+{
+ char *input_name;
+
+ if ((input_name = (char *) calloc (1, 255)) == 0) {
+ com_err("check_security",
+ ENOMEM, "while allocating memory for class check");
+ return(3);
+ }
+
+ memcpy((char *) input_name, princ->data[0].data, princ->data[0].length);
+
+ if (class) {
+ /* Must be Classified Principal */
+ if (strlen(input_name) == 8) {
+ if (!(strcmp(&input_name[7], "s") == 0) &&
+ !(strcmp(&input_name[7], "c") == 0)) {
+ free(input_name);
+ return(6);
+ }
+ } else {
+ if (!((strncmp(&input_name[strlen(input_name) - 2],
+ "_s", 2) == 0) ||
+ (strncmp(&input_name[strlen(input_name) - 2], "_c", 2) == 0))) {
+ free(input_name);
+ return(6);
+ }
+ }
+ } else {
+ /* Must be Unclassified Principal */
+ if ((strlen(input_name) >= 8) ||
+ ((strncmp(&input_name[strlen(input_name) - 2], "_s", 2) == 0) ||
+ (strncmp(&input_name[strlen(input_name) - 2], "_c", 2) == 0))) {
+ free(input_name);
+ return(6);
+ }
+ }
+
+ free(input_name);
+ return(0);
+}
+#endif
--- /dev/null
+/*
+ * kadmin/server/adm_check.c
+ *
+ * Copyright 1990,1991 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * 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. 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.
+ *
+ * Sandia National Laboratories also makes no representations about the
+ * suitability of the modifications, or additions to this software for
+ * any purpose. It is provided "as is" without express or implied warranty.
+ *
+ */
+
+
+#include <sys/types.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <syslog.h>
+#include "com_err.h"
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#ifndef hpux
+#include <arpa/inet.h>
+#endif
+
+#include "k5-int.h"
+#include "adm_err.h"
+#include "adm_extern.h"
+
+krb5_error_code
+adm_check_acl(name_of_client, acl_type)
+ char *name_of_client;
+ char *acl_type;
+{
+ FILE *acl_file;
+ char input_string[255];
+ char admin_name[255];
+#define num_of_privs 5
+ char priv[num_of_privs];
+ extern char *acl_file_name;
+ char *lcl_acl_file;
+ int i, j;
+
+ if ((lcl_acl_file = (char *) calloc(1, 80)) == (char *) 0) {
+ com_err("adm_check_acl", ENOMEM, "allocating acl file name");
+ return(KADM_ENOMEM); /* No Memory */
+ }
+
+ (void) sprintf(lcl_acl_file, "%s", acl_file_name);
+
+ if ((acl_file = fopen(lcl_acl_file, "r")) == NULL) {
+ syslog(LOG_ERR, "Cannot open acl file (%s)", acl_file_name);
+ free(lcl_acl_file);
+ return(KADM_EPERM);
+ }
+
+ for ( ;; ) {
+
+ if ((fgets(input_string, sizeof(input_string), acl_file)) == NULL) {
+ syslog(LOG_ERR, "Administrator (%s) not in ACL file (%s)",
+ name_of_client, lcl_acl_file);
+ break; /* Not Found */
+ }
+
+ if (input_string[0] == '#') continue;
+
+ i = 0;
+ while (!isspace(input_string[i]) && i < strlen(input_string)) {
+ admin_name[i] = input_string[i];
+ i++;
+ }
+
+ while (isspace(input_string[i]) && i < strlen(input_string)) {
+ i++;
+ }
+
+ priv[0] = priv[1] = priv[2] = priv[3] = priv[4] = '\0';
+
+ j = 0;
+ while ((i < strlen(input_string)) && (j < num_of_privs) &&
+ (!isspace(input_string[i]))) {
+ priv[j] = input_string[i];
+ i++; j++;
+ }
+
+ if (priv[0] == '*') {
+ priv[0] = 'a'; /* Add Priv */
+ priv[1] = 'c'; /* Changepw Priv */
+ priv[2] = 'd'; /* Delete Priv */
+ priv[3] = 'i'; /* Inquire Priv */
+ priv[4] = 'm'; /* Modify Priv */
+ }
+
+ if (!strncmp(admin_name, name_of_client,
+ strlen(name_of_client))) {
+ switch(acl_type[0]) {
+ case 'a':
+ case 'c':
+ case 'd':
+ case 'i':
+ case 'm':
+ for (i = 0; i < num_of_privs; i++) {
+ if (priv[i] == acl_type[0]) {
+ fclose(acl_file);
+ free(lcl_acl_file);
+ return(0); /* Found */
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+
+ fclose(acl_file);
+ free(lcl_acl_file);
+ return(KADM_EPERM);
+}
--- /dev/null
+/*
+ * kadmin/server/adm_extern.c
+ *
+ * Copyright 1990 by the Massachusetts Institute of Technology.
+ *
+ * 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. 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.
+ *
+ *
+ * Sandia National Laboratories also makes no representations about the
+ * suitability of the modifications, or additions to this software for
+ * any purpose. It is provided "as is" without express or implied warranty.
+ *
+ * allocations of adm_extern stuff
+ */
+
+#include "k5-int.h"
+
+/* real declarations of KDC's externs */
+krb5_encrypt_block master_encblock;
+krb5_keyblock master_keyblock;
+krb5_principal master_princ;
+
+volatile int signal_requests_exit = 0; /* gets set when signal hits */
+
+char *dbm_db_name = DEFAULT_KDB_FILE;
+char *realm = NULL;
+
+krb5_keyblock tgs_key;
+krb5_kvno tgs_kvno;
+
+krb5_data inbuf;
+krb5_data msg_data;
+
+int send_seqno;
+
+/*
+static krb5_data tgs_name = {KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME};
+krb5_data *tgs_server[4] = {0, &tgs_name, 0, 0};
+*/
+
+krb5_principal tgs_server;
+
+short admin_port = 0;
--- /dev/null
+/*
+ * kadmin/server/adm_extern.h
+ *
+ * Copyright 1990 by the Massachusetts Institute of Technology.
+ *
+ * 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. 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.
+ *
+ * Sandia National Laboratories also makes no representations about the
+ * suitability of the modifications, or additions to this software for
+ * any purpose. It is provided "as is" without express or implied warranty.
+ *
+ * <<< Description >>>
+ */
+
+#ifndef __ADM_EXTERN__
+#define __ADM_EXTERN__
+
+#include "adm_defs.h"
+
+typedef struct {
+ /* Client Info */
+ struct sockaddr_in client_name;
+ krb5_address client_addr;
+ krb5_principal client;
+ char *name_of_client;
+ /* Server Info */
+ struct sockaddr_in server_name;
+ krb5_address server_addr;
+ krb5_principal server;
+ char *name_of_service;
+ /* Miscellaneous */
+ int server_socket;
+ int client_socket;
+} global_client_server_info;
+
+/* various externs for KDC */
+extern krb5_encrypt_block master_encblock;
+extern krb5_keyblock master_keyblock;
+extern krb5_principal master_princ;
+extern krb5_db_entry master_entry;
+
+extern volatile int signal_requests_exit;
+extern char *dbm_db_name;
+extern char *realm;
+
+extern krb5_keyblock tgs_key;
+extern krb5_kvno tgs_kvno;
+extern krb5_principal tgs_server;
+
+extern global_client_server_info client_server_info;
+extern char *adm5_tcp_portname;
+extern int adm5_tcp_port_fd;
+
+extern unsigned pidarraysize;
+extern int *pidarray;
+
+extern char *adm5_ver_str;
+extern int adm5_ver_len;
+
+extern int adm_debug_flag;
+
+extern int send_seqno;
+
+extern int exit_now;
+
+extern short admin_port;
+
+extern krb5_data inbuf;
+extern krb5_data msg_data;
+
+extern char *oper_type[];
+extern char *ksrvutil_message[];
+extern char *kadmind_general_response[];
+extern char *kadmind_kpasswd_response[];
+extern char *kadmind_ksrvutil_response[];
+extern char *kadmind_kadmin_response[];
+
+/* PROTOTYPES */
+
+krb5_error_code adm_build_key
+ PROTOTYPE((krb5_context,
+ krb5_auth_context *,
+ char *,
+ int,
+ krb5_db_entry));
+
+krb5_error_code adm_change_pwd
+ PROTOTYPE((krb5_context,
+ krb5_auth_context *,
+ char *,
+ char *,
+ int));
+
+krb5_error_code adm_change_pwd_rnd
+ PROTOTYPE((krb5_context,
+ char *,
+ char *));
+
+krb5_error_code adm_add_new_key
+ PROTOTYPE((krb5_context,
+ krb5_auth_context *,
+ char *,
+ char *,
+ int));
+
+krb5_error_code adm_add_new_key_rnd
+ PROTOTYPE((krb5_context,
+ char *,
+ char *));
+
+krb5_error_code adm_del_old_key
+ PROTOTYPE((krb5_context,
+ char *,
+ char *));
+
+krb5_error_code adm_mod_old_key
+ PROTOTYPE((krb5_context,
+ krb5_auth_context *,
+ char *,
+ char *));
+
+krb5_error_code adm_inq_old_key
+ PROTOTYPE((krb5_context,
+ krb5_auth_context *,
+ char *,
+ char *));
+
+krb5_error_code adm_print_exp_time
+ PROTOTYPE((krb5_context,
+ char *,
+ krb5_timestamp));
+
+krb5_kvno adm_princ_exists
+ PROTOTYPE((krb5_context,
+ char *,
+ krb5_principal,
+ krb5_db_entry *,
+ int *));
+
+krb5_error_code adm_enter_rnd_pwd_key
+ PROTOTYPE((krb5_context,
+ char *,
+ krb5_principal,
+ int,
+ krb5_db_entry *));
+
+krb5_error_code adm5_kadmin
+ PROTOTYPE((krb5_context,
+ krb5_auth_context *,
+ char *,
+ char *,
+ int *));
+
+krb5_error_code adm_negotiate_key
+ PROTOTYPE((krb5_context,
+ krb5_auth_context *,
+ char const *,
+ char *));
+
+krb5_error_code setup_network
+ PROTOTYPE((krb5_context,
+ const char *));
+
+krb5_error_code process_client
+ PROTOTYPE((krb5_context,
+ char *));
+
+krb5_error_code cleanexit
+ PROTOTYPE((krb5_context,
+ int));
+
+krb5_error_code closedown_db
+ PROTOTYPE((krb5_context));
+
+krb5_error_code process_args
+ PROTOTYPE((krb5_context,
+ int,
+ char **));
+
+krb5_error_code init_db
+ PROTOTYPE((krb5_context,
+ char *,
+ krb5_principal,
+ krb5_keyblock *));
+
+void setup_com_err
+ PROTOTYPE((krb5_context));
+
+krb5_error_code princ_exists
+ PROTOTYPE((krb5_context,
+ krb5_principal,
+ krb5_db_entry *));
+
+krb5_error_code adm_enter_pwd_key
+ PROTOTYPE((krb5_context,
+ char * ,
+ char * ,
+ krb5_const_principal ,
+ krb5_const_principal ,
+ int ,
+ int ,
+ char * ,
+ krb5_db_entry * ));
+
+krb5_error_code adm5_change
+ PROTOTYPE((krb5_context,
+ krb5_auth_context *,
+ char *,
+ krb5_principal));
+
+int adm5_listen_and_process
+ PROTOTYPE((krb5_context,
+ const char *));
+
+krb5_error_code adm5_kpasswd
+ PROTOTYPE((krb5_context,
+ krb5_auth_context *,
+ char *,
+ kadmin_requests *,
+ char *,
+ int *));
+
+#endif /* __ADM_EXTERN__ */
--- /dev/null
+/*
+ * kadmin/server/adm_fmt_inq.c
+ *
+ * Copyright 1990,1991 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * 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. 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.
+ *
+ * Sandia National Laboratories also makes no representations about the
+ * suitability of the modifications, or additions to this software for
+ * any purpose. It is provided "as is" without express or implied warranty.
+ *
+ * Administrative Display Routine
+ */
+
+#include "k5-int.h"
+#include <stdio.h>
+
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#ifdef TIME_WITH_SYS_TIME
+#include <time.h>
+#endif
+#else
+#include <time.h>
+#endif
+
+#define REALM_SEP '@'
+#define REALM_SEP_STR "@"
+
+krb5_error_code
+adm_print_attributes(ret_data, attribs)
+char *ret_data;
+krb5_flags attribs;
+{
+ char *my_data;
+
+ if ((my_data = (char *) calloc (1,255)) == (char *) 0)
+ return ENOMEM;
+
+ sprintf(my_data, "Principal Attributes (PA): ");
+ if (attribs & KRB5_KDB_DISALLOW_POSTDATED)
+ strcat(my_data, "NOPOST ");
+ else
+ strcat(my_data, "POST ");
+ if (attribs & KRB5_KDB_DISALLOW_FORWARDABLE)
+ strcat(my_data, "NOFOR ");
+ else
+ strcat(my_data, "FOR ");
+ if (attribs & KRB5_KDB_DISALLOW_TGT_BASED)
+ strcat(my_data, "NOTGT ");
+ else
+ strcat(my_data, "TGT ");
+ if (attribs & KRB5_KDB_DISALLOW_RENEWABLE)
+ strcat(my_data, "NOREN ");
+ else
+ strcat(my_data, "REN ");
+ if (attribs & KRB5_KDB_DISALLOW_PROXIABLE)
+ strcat(my_data, "NOPROXY\n");
+ else
+ strcat(my_data, "PROXY\n");
+ strcat(my_data, " ");
+ if (attribs & KRB5_KDB_DISALLOW_DUP_SKEY)
+ strcat(my_data, "NODUPSKEY ");
+ else
+ strcat(my_data, "DUPSKEY ");
+ if (attribs & KRB5_KDB_DISALLOW_ALL_TIX)
+ strcat(my_data, "LOCKED ");
+ else
+ strcat(my_data, "UNLOCKED ");
+ if (attribs & KRB5_KDB_DISALLOW_SVR)
+ strcat(my_data, "NOSVR\n");
+ else
+ strcat(my_data, "SVR\n");
+
+#ifdef SANDIA
+ strcat(my_data, " ");
+ if (attribs & KRB5_KDB_REQUIRES_PRE_AUTH)
+ strcat(my_data, "PREAUTH ");
+ else
+ strcat(my_data, "NOPREAUTH ");
+ if (attribs & KRB5_KDB_REQUIRES_PWCHANGE)
+ strcat(my_data, "PWCHG ");
+ else
+ strcat(my_data, "PWOK ");
+ if (attribs & KRB5_KDB_REQUIRES_HW_AUTH)
+ strcat(my_data, "SID\n");
+ else
+ strcat(my_data, "NOSID\n");
+#endif
+ (void) strcat(ret_data, my_data);
+ free(my_data);
+ return(0);
+}
+
+krb5_error_code
+adm_print_exp_time(context, ret_data, time_input)
+ krb5_context context;
+ char *ret_data;
+ krb5_timestamp *time_input;
+{
+ char *my_data;
+ struct tm *exp_time;
+
+ if ((my_data = (char *) calloc (1,255)) == (char *) 0)
+ return ENOMEM;
+
+ exp_time = localtime((time_t *) time_input);
+ sprintf(my_data,
+ "Principal Expiration Date (PED): %02d%02d/%02d/%02d:%02d:%02d:%02d\n",
+ (exp_time->tm_year >= 100) ? 20 : 19,
+ (exp_time->tm_year >= 100) ? exp_time->tm_year - 100 : exp_time->tm_year,
+ exp_time->tm_mon + 1,
+ exp_time->tm_mday,
+ exp_time->tm_hour,
+ exp_time->tm_min,
+ exp_time->tm_sec);
+ (void) strcat(ret_data, my_data);
+ free(my_data);
+ return(0);
+}
+
+krb5_error_code
+adm_fmt_prt(context, entry, Principal_name, ret_data)
+ krb5_context context;
+ krb5_db_entry *entry;
+ char *Principal_name;
+ char *ret_data;
+{
+ struct tm *mod_time;
+ krb5_error_code retval;
+#ifdef SANDIA
+ struct tm *exp_time;
+ int pwd_expire;
+ krb5_timestamp now;
+#endif
+
+ char *my_data;
+ char thisline[80];
+
+ if ((my_data = (char *) calloc (1, 2048)) == (char *) 0)
+ return ENOMEM;
+
+ (void) sprintf(my_data, "\n\nPrincipal: %s\n\n", Principal_name);
+ sprintf(thisline,
+ "Maximum Ticket Lifetime (MTL) = %d (seconds)\n", entry->max_life);
+ strcat(my_data, thisline);
+ sprintf(thisline, "Maximum Renewal Lifetime (MRL) = %d (seconds)\n",
+ entry->max_renewable_life);
+ strcat(my_data, thisline);
+ sprintf(thisline, "Principal Key Version (PKV) = %d\n", entry->kvno);
+ strcat(my_data, thisline);
+ if (retval = adm_print_exp_time(context, my_data, &entry->expiration)) {
+ free(my_data);
+ return retval;
+ }
+ mod_time = localtime((time_t *) &entry->mod_date);
+ sprintf(thisline,
+ "Last Modification Date (LMD): %02d%02d/%02d/%02d:%02d:%02d:%02d\n",
+ (mod_time->tm_year >= 100) ? 20 : 19,
+ (mod_time->tm_year >= 100) ? mod_time->tm_year - 100 : mod_time->tm_year,
+ mod_time->tm_mon + 1,
+ mod_time->tm_mday,
+ mod_time->tm_hour,
+ mod_time->tm_min,
+ mod_time->tm_sec);
+ strcat(my_data, thisline);
+ if (retval = adm_print_attributes(my_data, entry->attributes)) {
+ free(my_data);
+ return retval;
+ }
+ switch (entry->salt_type & 0xff) {
+ case 0 : strcat(my_data,
+ "Principal Salt Type (PST) = Version 5 Normal\n");
+ break;
+ case 1 : strcat(my_data, "Principal Salt Type (PST) = Version 4\n");
+ break;
+ case 2 : strcat(my_data, "Principal Salt Type (PST) = NOREALM\n");
+ break;
+ case 3 : strcat(my_data, "Principal Salt Type (PST) = ONLYREALM\n");
+ break;
+ case 4 : strcat(my_data, "Principal Salt Type (PST) = Special\n");
+ break;
+ }
+#ifdef SANDIA
+ sprintf(thisline,
+ "Invalid Authentication Count (FCNT) = %d\n", entry->fail_auth_count);
+ strcat(my_data, thisline);
+ retval = krb5_timeofday(context, &now);
+ pwd_expire = (now - entry->last_pwd_change) / 86400;
+ sprintf(thisline, "Password Age is %d Days\n", pwd_expire);
+ strcat(my_data, thisline);
+#endif
+ (void) strcat(ret_data, my_data);
+ free(my_data);
+ return(0);
+}
--- /dev/null
+/*
+ * kadmin/server/adm_funcs.c
+ *
+ * Copyright 1990,1991 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * 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. 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.
+ *
+ * Sandia National Laboratories also makes no representations about the
+ * suitability of the modifications, or additions to this software for
+ * any purpose. It is provided "as is" without express or implied warranty.
+ *
+ * Modify the Kerberos Database
+ */
+
+#include "com_err.h"
+#include <sys/types.h>
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#ifndef hpux
+#include <arpa/inet.h>
+#endif
+
+#include "k5-int.h"
+#include "adm_err.h"
+#include "adm_extern.h"
+
+struct saltblock {
+ int salttype;
+ krb5_data saltdata;
+};
+
+extern krb5_encrypt_block master_encblock;
+extern krb5_keyblock master_keyblock;
+
+typedef unsigned char des_cblock[8];
+
+krb5_error_code adm_get_rnd_key PROTOTYPE((char *,
+ krb5_ticket *,
+ krb5_authenticator *,
+ krb5_principal,
+ int,
+ krb5_db_entry *));
+
+static krb5_error_code adm_modify_kdb
+ PROTOTYPE((krb5_context,
+ char const *,
+ char const *,
+ krb5_const_principal,
+ const krb5_keyblock *,
+ const krb5_keyblock *,
+ int,
+ struct saltblock *,
+ struct saltblock *,
+ krb5_db_entry *));
+
+
+krb5_kvno
+adm_princ_exists(context, cmdname, principal, entry, nprincs)
+ krb5_context context;
+ char *cmdname;
+ krb5_principal principal;
+ krb5_db_entry *entry;
+ int *nprincs;
+{
+ krb5_boolean more;
+ krb5_error_code retval;
+
+ if (retval = krb5_db_get_principal(context, principal, entry,
+ nprincs, &more)) {
+ com_err("adm_princ_exists", retval,
+ "while attempting to verify principal's existence");
+ return(0);
+ }
+
+ if (! *nprincs) return(0);
+
+ return(*nprincs);
+}
+
+static krb5_error_code
+adm_modify_kdb(context, cmdname, newprinc, principal, key, alt_key, req_type,
+ salt, altsalt, entry)
+ krb5_context context;
+ char const * cmdname;
+ char const * newprinc;
+ krb5_const_principal principal;
+ const krb5_keyblock * key;
+ const krb5_keyblock * alt_key;
+ int req_type;
+ struct saltblock * salt;
+ struct saltblock * altsalt;
+ krb5_db_entry * entry;
+{
+ krb5_error_code retval;
+ int one = 1;
+
+ krb5_kvno KDB5_VERSION_NUM = 1;
+ extern krb5_flags NEW_ATTRIBUTES;
+
+ if (!req_type) { /* New entry - initialize */
+ memset((char *) entry, 0, sizeof(krb5_db_entry));
+ retval = krb5_copy_principal(context, principal, &entry->principal);
+ if (retval)
+ return retval;
+ entry->kvno = KDB5_VERSION_NUM;
+ entry->max_life = master_entry.max_life;
+ entry->max_renewable_life = master_entry.max_renewable_life;
+ entry->mkvno = master_entry.mkvno;
+ entry->expiration = master_entry.expiration;
+ retval = krb5_copy_principal(context, master_princ, &entry->mod_name);
+ if (retval) {
+ krb5_free_principal(context, entry->principal);
+ entry->principal = 0;
+ return retval;
+ }
+ } else { /* Modify existing entry */
+ entry->kvno++;
+#ifdef SANDIA
+ entry->attributes &= ~KRB5_KDB_REQUIRES_PWCHANGE;
+#endif
+ retval = krb5_copy_principal(context, principal, &entry->mod_name);
+ if (retval)
+ return retval;
+ }
+
+ if (key && key->length) {
+ retval = krb5_kdb_encrypt_key(context, &master_encblock,
+ key,
+ &entry->key);
+ if (retval) {
+ com_err("adm_modify_kdb", retval,
+ "while encrypting key for '%s'", newprinc);
+ return(KADM_NO_ENCRYPT);
+ }
+ }
+
+ if (alt_key && alt_key->length) {
+ retval = krb5_kdb_encrypt_key(context, &master_encblock,
+ alt_key,
+ &entry->alt_key);
+ if (retval) {
+ if (entry->key.contents) {
+ memset((char *) entry->key.contents, 0, entry->key.length);
+ krb5_xfree(entry->key.contents);
+ entry->key.contents = 0;
+ }
+ com_err("adm_modify_kdb", retval,
+ "while encrypting alt_key for '%s'", newprinc);
+ return(KADM_NO_ENCRYPT);
+ }
+ }
+
+ if (retval = krb5_timeofday(context, &entry->mod_date)) {
+ com_err("adm_modify_kdb", retval, "while fetching date");
+ if (entry->key.contents) {
+ memset((char *) entry->key.contents, 0, entry->key.length);
+ krb5_xfree(entry->key.contents);
+ entry->key.contents = 0;
+ }
+ if (entry->alt_key.contents) {
+ krb5_xfree(entry->alt_key.contents);
+ memset((char *) entry->alt_key.contents, 0, entry->alt_key.length);
+ entry->alt_key.contents = 0;
+ }
+ return(KRB_ERR_GENERIC);
+ }
+
+ if (!req_type) {
+ if (salt->salttype == KRB5_KDB_SALTTYPE_V4) {
+ entry->attributes = (KRB5_KDB_DISALLOW_DUP_SKEY | NEW_ATTRIBUTES)
+#ifdef SANDIA
+ & ~KRB5_KDB_REQUIRES_PRE_AUTH & ~KRB5_KDB_REQUIRES_HW_AUTH
+#endif
+ ;
+ } else {
+ entry->attributes = NEW_ATTRIBUTES;
+ }
+
+#ifdef SANDIA
+ entry->last_pwd_change = entry->mod_date;
+ entry->last_success = entry->mod_date;
+ entry->fail_auth_count = 0;
+#endif
+
+ if (salt) {
+ entry->salt_type = salt->salttype;
+ entry->salt_length = salt->saltdata.length;
+ entry->salt = (krb5_octet *) salt->saltdata.data;
+ } else {
+ entry->salt_type = KRB5_KDB_SALTTYPE_NORMAL;
+ entry->salt_length = 0;
+ entry->salt = 0;
+ }
+
+ /* Set up version 4 alt key and alt salt info.....*/
+ if (altsalt) {
+ entry->alt_salt_type = altsalt->salttype;
+ entry->alt_salt_length = altsalt->saltdata.length;
+ entry->alt_salt = (krb5_octet *) altsalt->saltdata.data;
+ } else {
+ entry->alt_salt_type = KRB5_KDB_SALTTYPE_NORMAL;
+ entry->alt_salt_length = 0;
+ entry->alt_salt = 0;
+ }
+ } else {
+ if (retval = krb5_timeofday(context, &entry->last_pwd_change)) {
+ com_err("adm_modify_kdb", retval, "while fetching date");
+ if (entry->key.contents) {
+ memset((char *) entry->key.contents, 0, entry->key.length);
+ krb5_xfree(entry->key.contents);
+ entry->key.contents = 0;
+ }
+ if (entry->alt_key.contents) {
+ memset((char *) entry->alt_key.contents, 0,
+ entry->alt_key.length);
+ krb5_xfree(entry->alt_key.contents);
+ entry->alt_key.contents = 0;
+ }
+ return(5);
+ }
+ }
+
+ retval = krb5_db_put_principal(context, entry, &one);
+
+ if (entry->key.contents) {
+ memset((char *) entry->key.contents, 0, entry->key.length);
+ krb5_xfree(entry->key.contents);
+ entry->key.contents = 0;
+ }
+
+ if (entry->alt_key.contents) {
+ memset((char *) entry->alt_key.contents, 0, entry->alt_key.length);
+ krb5_xfree(entry->alt_key.contents);
+ entry->alt_key.contents = 0;
+ }
+
+ if (retval) {
+ com_err("adm_modify_kdb", retval,
+ "while storing entry for '%s'\n", newprinc);
+ return(kdb5_err_base + retval);
+ }
+
+ if (one != 1)
+ com_err("adm_modify_kdb", 0, "entry not stored in database (unknown failure)");
+ return(0);
+}
+
+krb5_error_code
+adm_enter_pwd_key(context, cmdname, newprinc, princ, string_princ, req_type,
+ salttype, new_password, entry)
+ krb5_context context;
+ char * cmdname;
+ char * newprinc;
+ krb5_const_principal princ;
+ krb5_const_principal string_princ;
+ int req_type;
+ int salttype;
+ char * new_password;
+ krb5_db_entry * entry;
+{
+ krb5_error_code retval;
+ krb5_keyblock tempkey;
+ krb5_data pwd;
+ struct saltblock salt;
+ struct saltblock altsalt;
+ krb5_keyblock alttempkey;
+
+ pwd.data = new_password;
+ pwd.length = strlen((char *) new_password);
+
+ salt.salttype = salttype;
+
+ tempkey.contents = alttempkey.contents = 0;
+ retval = KRB_ERR_GENERIC;
+
+ switch (salttype) {
+ case KRB5_KDB_SALTTYPE_NORMAL:
+ if (retval = krb5_principal2salt(context,string_princ,&salt.saltdata)) {
+ com_err("adm_enter_pwd_key", retval,
+ "while converting principal to salt for '%s'", newprinc);
+ goto cleanup;
+ }
+
+ altsalt.salttype = KRB5_KDB_SALTTYPE_V4;
+ altsalt.saltdata.data = 0;
+ altsalt.saltdata.length = 0;
+ break;
+
+ case KRB5_KDB_SALTTYPE_V4:
+ salt.saltdata.data = 0;
+ salt.saltdata.length = 0;
+ if (retval = krb5_principal2salt(context, string_princ,
+ &altsalt.saltdata)) {
+ com_err("adm_enter_pwd_key", retval,
+ "while converting principal to altsalt for '%s'", newprinc);
+ goto cleanup;
+ }
+
+ altsalt.salttype = KRB5_KDB_SALTTYPE_NORMAL;
+ break;
+
+ case KRB5_KDB_SALTTYPE_NOREALM:
+ if (retval = krb5_principal2salt_norealm(context, string_princ,
+ &salt.saltdata)) {
+ com_err("adm_enter_pwd_key", retval,
+ "while converting principal to salt for '%s'", newprinc);
+ goto cleanup;
+ }
+
+ altsalt.salttype = KRB5_KDB_SALTTYPE_V4;
+ altsalt.saltdata.data = 0;
+ altsalt.saltdata.length = 0;
+ break;
+
+ case KRB5_KDB_SALTTYPE_ONLYREALM:
+ {
+ krb5_data *foo;
+ if (retval = krb5_copy_data(context,
+ krb5_princ_realm(context, string_princ),
+ &foo)) {
+ com_err("adm_enter_pwd_key", retval,
+ "while converting principal to salt for '%s'", newprinc);
+ goto cleanup;
+ }
+
+ salt.saltdata = *foo;
+ krb5_xfree(foo);
+ altsalt.salttype = KRB5_KDB_SALTTYPE_V4;
+ altsalt.saltdata.data = 0;
+ altsalt.saltdata.length = 0;
+ break;
+ }
+
+ default:
+ com_err("adm_enter_pwd_key", 0,
+ "Don't know how to enter salt type %d", salttype);
+ goto cleanup;
+ }
+
+ if (retval = krb5_string_to_key(context, &master_encblock,
+ master_keyblock.keytype,
+ &tempkey,
+ &pwd,
+ &salt.saltdata)) {
+ com_err("adm_enter_pwd_key", retval,
+ "while converting password to key for '%s'", newprinc);
+ goto cleanup;
+ }
+
+ if (retval = krb5_string_to_key(context, &master_encblock,
+ master_keyblock.keytype,
+ &alttempkey,
+ &pwd,
+ &altsalt.saltdata)) {
+ com_err("adm_enter_pwd_key", retval,
+ "while converting password to alt_key for '%s'", newprinc);
+ goto cleanup;
+ }
+
+ memset((char *) new_password, 0, sizeof(new_password)); /* erase it */
+
+ retval = adm_modify_kdb(context, "adm_enter_pwd_key",
+ newprinc,
+ princ,
+ &tempkey,
+ &alttempkey,
+ req_type,
+ &salt,
+ &altsalt,
+ entry);
+
+cleanup:
+ if (salt.saltdata.data)
+ krb5_xfree(salt.saltdata.data);
+ if (altsalt.saltdata.data)
+ krb5_xfree(altsalt.saltdata.data);
+ if (tempkey.contents) {
+ memset((char *) tempkey.contents, 0, tempkey.length);
+ krb5_xfree(tempkey.contents);
+ }
+ if (alttempkey.contents) {
+ memset((char *) alttempkey.contents, 0, alttempkey.length);
+ krb5_xfree(alttempkey.contents);
+ }
+ memset((char *) new_password, 0, pwd.length); /* erase password */
+ return(retval);
+}
+
+krb5_error_code
+adm5_change(context, auth_context, prog, newprinc)
+ krb5_context context;
+ krb5_auth_context * auth_context;
+ char *prog;
+ krb5_principal newprinc;
+{
+ krb5_db_entry entry;
+ int nprincs = 1;
+
+ krb5_error_code retval;
+ char *composite_name;
+ char new_passwd[ADM_MAX_PW_LENGTH + 1];
+
+ if (!(adm_princ_exists(context, "adm5_change", newprinc,
+ &entry, &nprincs))) {
+ com_err("adm5_change", 0, "No principal exists!");
+ krb5_free_principal(context, newprinc);
+ return(1);
+ }
+
+ memset((char *) new_passwd, 0, ADM_MAX_PW_LENGTH + 1);
+
+ /* Negotiate for New Key */
+ if (retval = adm_negotiate_key(context, auth_context, "adm5_change",
+ new_passwd)) {
+ krb5_db_free_principal(context, &entry, nprincs);
+ krb5_free_principal(context, newprinc);
+ return(1);
+ }
+
+ if (retval = krb5_unparse_name(context, newprinc, &composite_name)) {
+ krb5_free_principal(context, newprinc);
+ krb5_db_free_principal(context, &entry, nprincs);
+ return retval;
+ }
+
+ if (entry.salt_type == KRB5_KDB_SALTTYPE_V4) {
+ entry.salt_type = KRB5_KDB_SALTTYPE_NORMAL;
+ entry.alt_salt_type = KRB5_KDB_SALTTYPE_V4;
+ com_err("adm5_change", 0, "Converting v4user to v5user");
+ }
+
+ retval = adm_enter_pwd_key(context, "adm5_change",
+ composite_name,
+ newprinc,
+ newprinc,
+ 1, /* change */
+ KRB5_KDB_SALTTYPE_NORMAL,
+ new_passwd,
+ &entry);
+ (void) memset(new_passwd, 0, strlen(new_passwd));
+ krb5_free_principal(context, newprinc);
+ krb5_db_free_principal(context, &entry, nprincs);
+ free(composite_name);
+ return(retval);
+}
+
+#ifdef SANDIA
+krb5_error_code
+adm5_create_rnd(prog, change_princ, client_auth_data, client_creds)
+char *prog;
+krb5_principal change_princ;
+krb5_authenticator *client_auth_data;
+krb5_ticket *client_creds;
+{
+ krb5_db_entry entry;
+ int nprincs = 1;
+
+ krb5_error_code retval;
+
+ if (!(adm_princ_exists("adm5_create_rnd",
+ change_princ,
+ &entry,
+ &nprincs))) {
+ com_err("adm5_create_rnd", 0, "No principal exists!");
+ krb5_free_principal(change_princ);
+ return(1);
+ }
+
+ if (retval = adm_get_rnd_key("adm5_create_rnd",
+ client_creds,
+ client_auth_data,
+ change_princ,
+ 1, /* change */
+ &entry)) {
+ krb5_db_free_principal(&entry, nprincs);
+ krb5_free_principal(change_princ);
+ return(retval);
+ }
+
+ krb5_free_principal(change_princ);
+ krb5_db_free_principal(&entry, nprincs);
+ return(0);
+}
+#endif
+#define MAXMSGSZ 255
+
+krb5_error_code
+adm_enter_rnd_pwd_key(context, cmdname, change_princ, req_type, entry)
+ krb5_context context;
+ char * cmdname;
+ krb5_principal change_princ;
+ int req_type;
+ krb5_db_entry * entry;
+{
+ krb5_error_code retval;
+ krb5_keyblock *tempkey;
+ krb5_pointer master_random;
+ int salttype = KRB5_KDB_SALTTYPE_NORMAL;
+ struct saltblock salt;
+ char *principal_name;
+
+ salt.salttype = salttype;
+ entry->salt_type = salttype;
+
+ if (retval = krb5_init_random_key(context, &master_encblock,
+ &master_keyblock,
+ &master_random)) {
+ com_err("adm_enter_rnd_pwd_key", 0, "Unable to Initialize Random Key");
+ (void) krb5_finish_key(context, &master_encblock);
+ memset((char *)master_keyblock.contents, 0, master_keyblock.length);
+ krb5_xfree(master_keyblock.contents);
+ goto finish;
+ }
+
+ /* Get Random Key */
+ if (retval = krb5_random_key(context, &master_encblock,
+ master_random,
+ &tempkey)) {
+ com_err("adm_enter_rnd_pwd_key", 0, "Unable to Obtain Random Key");
+ goto finish;
+ }
+
+ /* Tie the Random Key to the Principal */
+ if (retval = krb5_principal2salt(context, change_princ, &salt.saltdata)) {
+ com_err("adm_enter_rnd_pwd_key", 0, "Principal2salt Failure");
+ goto finish;
+ }
+
+ if (retval = krb5_unparse_name(context, change_princ, &principal_name))
+ goto finish;
+
+ /* Modify Database */
+ retval = adm_modify_kdb(context, "adm_enter_rnd_pwd_key",
+ principal_name,
+ change_princ,
+ tempkey,
+ tempkey,
+ req_type,
+ &salt,
+ &salt,
+ entry);
+ free(principal_name);
+
+ if (retval) {
+ com_err("adm_enter_rnd_pwd_key", 0, "Database Modification Failure");
+ retval = 2;
+ goto finish;
+ }
+
+ finish:
+
+ if (tempkey->contents) {
+ memset((char *) tempkey->contents, 0, tempkey->length);
+ krb5_free_keyblock(context, tempkey);
+ }
+
+ return(retval);
+}
--- /dev/null
+/*
+ * kadmin/server/adm_kadmin.c
+ *
+ * Copyright 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ *
+ */
+
+/*
+ * Sandia National Laboratories also makes no representations about the
+ * suitability of the modifications, or additions to this software for
+ * any purpose. It is provided "as is" without express or implied warranty.
+ */
+
+
+/*
+ adm_kadmin.c
+*/
+
+#include <sys/types.h>
+#include <syslog.h>
+#include "com_err.h"
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#ifndef hpux
+#include <arpa/inet.h>
+#endif
+
+#include "k5-int.h"
+#include "adm_extern.h"
+
+krb5_error_code
+adm5_kadmin(context, auth_context, prog, retbuf, otype)
+ krb5_context context;
+ krb5_auth_context * auth_context;
+ char *prog;
+ char *retbuf; /* Allocated in Calling Routine */
+ int *otype;
+{
+ krb5_replay_data replaydata;
+ krb5_error_code retval;
+ kadmin_requests request_type;
+ krb5_data msg_data, outbuf, inbuf;
+
+ char *customer_name;
+ char *completion_msg;
+ int length_of_name;
+
+ int salttype;
+
+ outbuf.data = retbuf; /* Do NOT free outbuf.data */
+
+ for ( ; ; ) { /* Use "return", "break", or "goto"
+ to exit for loop */
+
+ /* Encode Acknowledgement Message */
+ retbuf[0] = KADMIND;
+ retbuf[1] = KADMSAG;
+ retbuf[2] = SENDDATA2;
+ outbuf.length = 3;
+
+ retval = krb5_mk_priv(context, auth_context, &outbuf,
+ &msg_data, &replaydata);
+ if (retval ) {
+ syslog(LOG_ERR,
+ "adm5_kadmin - Error Performing Acknowledgement mk_priv");
+ return(5); /* Protocol Failure */
+ }
+
+ /* Send Acknowledgement Reply to Client */
+ if (retval = krb5_write_message(context, &client_server_info.client_socket,
+ &msg_data)){
+ free(msg_data.data);
+ syslog(LOG_ERR,
+ "adm5_kadmin - Error Performing Acknowledgement Write: %s",
+ error_message(retval));
+ return(5); /* Protocol Failure */
+ }
+ free(msg_data.data);
+
+ /* Read Username */
+ if (krb5_read_message(context, &client_server_info.client_socket, &inbuf)){
+ syslog(LOG_ERR | LOG_INFO, "Error Performing Username Read");
+ return(5); /* Protocol Failure */
+ }
+
+ /* Decrypt Client Response */
+ if ((retval = krb5_rd_priv(context, auth_context, &inbuf,
+ &msg_data, &replaydata))) {
+ free(inbuf.data);
+ syslog(LOG_ERR | LOG_INFO, "Error decoding Username - rd_priv");
+ return(5); /* Protocol Failure */
+ }
+ free(inbuf.data);
+
+ request_type.appl_code = msg_data.data[0];
+ request_type.oper_code = msg_data.data[1];
+ if (msg_data.data[2] != SENDDATA2) {
+ syslog(LOG_ERR | LOG_INFO,
+ "Invalid Protocol String - Response not SENDDATA2");
+ free(msg_data.data);
+ return(5); /* Protocol Failure */
+ }
+
+ length_of_name = msg_data.length - 3;
+
+ if (request_type.oper_code == COMPLETE) {
+ *otype = 0;
+ free(msg_data.data);
+ retval = 0;
+ goto finish_req;
+ }
+
+ if (!length_of_name) {
+ syslog(LOG_ERR,
+ "adm5_kadmin error: Invalid KADMIN request - No Customer");
+ free(msg_data.data);
+ return(5); /* Protocol Error */
+ }
+
+ if ((customer_name = (char *) calloc(1, length_of_name + 1)) ==
+ (char *) 0) {
+ syslog(LOG_ERR, "adm5_kadmin error: No Memory for Customer Name");
+ free(msg_data.data);
+ return(3); /* No Memory */
+ }
+
+ (void) memcpy(customer_name, (char *) msg_data.data + 3,
+ length_of_name);
+ customer_name[length_of_name] = '\0';
+
+ free(msg_data.data);
+
+ if ((completion_msg = (char *) calloc (1,512)) == (char *) 0) {
+ syslog(LOG_ERR, "adm5_kadmin - No Memory for completion_msg");
+ free(customer_name);
+ return(3); /* No Memory */
+ }
+
+ switch(request_type.oper_code) {
+ case ADDOPER:
+ /* Check for Add Privilege */
+ if (retval = adm_check_acl(client_server_info.name_of_client,
+ "a")) {
+ retval = 7;
+ goto process_retval;
+ }
+ *otype = 1;
+ salttype = KRB5_KDB_SALTTYPE_NORMAL;
+ retval = adm_add_new_key(context, auth_context, "adm5_kadmin",
+ customer_name, salttype);
+ goto process_retval;
+
+ case CHGOPER:
+ /* Check for Password Privilege */
+ if (retval = adm_check_acl(client_server_info.name_of_client,
+ "c")) {
+ retval = 7;
+ goto process_retval;
+ }
+ *otype = 2;
+ salttype = KRB5_KDB_SALTTYPE_NORMAL;
+ retval = adm_change_pwd(context, auth_context, "adm5_kadmin",
+ customer_name, salttype);
+ goto process_retval;
+
+ case ADROPER:
+ /* Check for Add Privilege */
+ if (retval = adm_check_acl(client_server_info.name_of_client,
+ "a")) {
+ retval = 7;
+ goto process_retval;
+ }
+ *otype = 3;
+ retval = adm_add_new_key_rnd(context, "adm5_kadmin",
+ customer_name);
+ goto process_retval;
+
+ case CHROPER:
+ /* Check for Password Privilege */
+ if (retval = adm_check_acl(client_server_info.name_of_client,
+ "c")) {
+ retval = 7;
+ goto process_retval;
+ }
+ *otype = 4;
+ retval = adm_change_pwd_rnd(context, "adm5_kadmin",
+ customer_name);
+ goto process_retval;
+
+ case DELOPER:
+ /* Check for Delete Privilege */
+ if (retval = adm_check_acl(client_server_info.name_of_client,
+ "d")) {
+ retval = 7;
+ goto process_retval;
+ }
+ *otype = 5;
+ retval = adm_del_old_key(context, "adm5_kadmin", customer_name);
+ goto process_retval;
+
+ case MODOPER:
+ /* Check for Modify Privilege */
+ if (retval = adm_check_acl(client_server_info.name_of_client,
+ "m")) {
+ retval = 7;
+ goto process_retval;
+ }
+ *otype = 6;
+ retval = adm_mod_old_key(context, auth_context, "adm5_kadmin",
+ customer_name);
+ goto process_retval;
+
+ case INQOPER:
+ /* Check for Inquiry Privilege */
+ if (retval = adm_check_acl(client_server_info.name_of_client,
+ "i")) {
+ retval = 7;
+ goto process_retval;
+ }
+ *otype = 7;
+ retval = adm_inq_old_key(context, auth_context, "adm5_kadmin",
+ customer_name);
+ goto process_retval;
+
+ case AD4OPER:
+ /* Check for Add Privilege */
+ if (retval = adm_check_acl(client_server_info.name_of_client,
+ "a")) {
+ retval = 7;
+ goto process_retval;
+ }
+ *otype = 8;
+ salttype = KRB5_KDB_SALTTYPE_V4;
+ retval = adm_add_new_key(context, auth_context, "adm5_kadmin",
+ customer_name, salttype);
+ goto process_retval;
+
+ case CH4OPER:
+ /* Check for Password Privilege */
+ if (retval = adm_check_acl(client_server_info.name_of_client,
+ "c")) {
+ retval = 7;
+ goto process_retval;
+ }
+ *otype = 9;
+ salttype = KRB5_KDB_SALTTYPE_V4;
+ retval = adm_change_pwd(context, auth_context, "adm5_kadmin",
+ customer_name, salttype);
+ goto process_retval;
+
+ default:
+ retbuf[0] = KADMIN;
+ retbuf[1] = KUNKNOWNOPER;
+ retbuf[2] = '\0';
+ sprintf(completion_msg, "%s %s from %s FAILED",
+ "kadmin",
+ "Unknown or Non-Implemented Operation Type!",
+ inet_ntoa(client_server_info.client_name.sin_addr));
+ syslog(LOG_AUTH | LOG_INFO, completion_msg);
+ retval = 255;
+ goto send_last;
+ } /* switch (request_type.oper_code) */
+
+process_retval:
+ switch (retval) {
+ case 0:
+ retbuf[0] = KADMIN;
+ retbuf[1] = request_type.oper_code;
+ retbuf[2] = KADMGOOD;
+ retbuf[3] = '\0';
+ goto send_last;
+
+ case 1: /* Principal Unknown */
+ case 2: /* Principal Already Exists */
+ case 3: /* ENOMEM */
+ case 4: /* Password Failure */
+ case 5: /* Protocol Failure */
+ case 6: /* Security Failure */
+ case 7: /* Admin Client Not in ACL List */
+ case 8: /* Database Update Failure */
+ retbuf[0] = KADMIN;
+ retbuf[1] = request_type.oper_code;
+ retbuf[2] = KADMBAD;
+ retbuf[3] = '\0';
+ sprintf((char *)retbuf +3, "%s",
+ kadmind_kadmin_response[retval]);
+ sprintf(completion_msg,
+ "%s %s from %s FAILED - %s",
+ "kadmin",
+ oper_type[request_type.oper_code],
+ inet_ntoa(client_server_info.client_name.sin_addr),
+ kadmind_kadmin_response[retval]);
+ syslog(LOG_AUTH | LOG_INFO, completion_msg);
+ goto send_last;
+
+ default:
+ retbuf[0] = KADMIN;
+ retbuf[1] = request_type.oper_code;
+ retbuf[2] = KUNKNOWNERR;
+ retbuf[3] = '\0';
+ sprintf(completion_msg, "%s %s from %s FAILED",
+ "kadmin",
+ oper_type[1],
+ inet_ntoa( client_server_info.client_name.sin_addr));
+ syslog(LOG_AUTH | LOG_INFO, completion_msg);
+ retval = 255;
+ goto send_last;
+ } /* switch(retval) */
+
+send_last:
+ free(customer_name);
+ free(completion_msg);
+ outbuf.data = retbuf;
+ outbuf.length = strlen(retbuf) + 1;
+
+ /* Send Completion Message */
+ if (retval = krb5_mk_priv(context, auth_context, &outbuf,
+ &msg_data, &replaydata)) {
+ syslog(LOG_ERR, "adm5_kadmin - Error Performing Final mk_priv");
+ return(1);
+ }
+
+ /* Send Final Reply to Client */
+ if (retval = krb5_write_message(context,
+ &client_server_info.client_socket,
+ &msg_data)){
+ free(msg_data.data);
+ syslog(LOG_ERR, "adm5_kadmin - Error Performing Final Write: %s",
+ error_message(retval));
+ return(1);
+ }
+ free(msg_data.data);
+ } /* for */
+
+finish_req:
+ return(retval);
+}
--- /dev/null
+/*
+ * kadmin/server/adm_kpasswd.c
+ *
+ * Copyright 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ *
+ */
+
+/*
+ * Sandia National Laboratories also makes no representations about the
+ * suitability of the modifications, or additions to this software for
+ * any purpose. It is provided "as is" without express or implied warranty.
+ */
+
+
+/*
+ adm_kpasswd.c
+*/
+
+#include <sys/types.h>
+#include <syslog.h>
+#include <sys/wait.h>
+#include <stdio.h>
+#include "com_err.h"
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#ifndef hpux
+#include <arpa/inet.h>
+#endif
+
+#include "k5-int.h"
+#include "adm_extern.h"
+
+extern krb5_encrypt_block master_encblock;
+extern krb5_keyblock master_keyblock;
+
+struct cpw_keyproc_arg {
+ krb5_keyblock *key;
+};
+
+krb5_error_code
+adm5_kpasswd(context, auth_context, prog, request_type, retbuf, otype)
+ krb5_context context;
+ krb5_auth_context *auth_context;
+ char *prog;
+ kadmin_requests *request_type;
+ char *retbuf;
+ int *otype;
+{
+ char completion_msg[520];
+ krb5_error_code retval;
+
+ switch (request_type->oper_code) {
+ case CHGOPER:
+ *otype = 3;
+ syslog(LOG_AUTH | LOG_INFO,
+ "adm_kpasswd: kpasswd change received");
+ retval = adm5_change(context, auth_context, "adm5_kpasswd",
+ client_server_info.client);
+
+ switch(retval) {
+ case 0:
+ retbuf[0] = KPASSWD;
+ retbuf[1] = CHGOPER;
+ retbuf[2] = KPASSGOOD;
+ retbuf[3] = '\0';
+ break;
+
+ case 1:
+ retbuf[0] = KPASSWD;
+ retbuf[1] = CHGOPER;
+ retbuf[2] = KPASSBAD;
+ retbuf[3] = '\0';
+ sprintf((char *)retbuf +3, "%s",
+ kadmind_kpasswd_response[retval]);
+ sprintf(completion_msg,
+ "kpasswd change from %s FAILED: %s",
+ inet_ntoa(client_server_info.client_name.sin_addr),
+ kadmind_kpasswd_response[retval]);
+ syslog(LOG_AUTH | LOG_INFO, completion_msg);
+ goto finish;
+
+ default:
+ retbuf[0] = KPASSWD;
+ retbuf[1] = CHGOPER;
+ retbuf[2] = KUNKNOWNERR;
+ retbuf[3] = '\0';
+ sprintf(completion_msg, "kpasswd change from %s FAILED",
+ inet_ntoa(client_server_info.client_name.sin_addr));
+ syslog(LOG_AUTH | LOG_INFO, completion_msg);
+ retval = 255;
+ goto finish;
+ } /* switch (retval) */
+ break;
+
+ default:
+ retbuf[0] = KPASSWD;
+ retbuf[1] = KUNKNOWNOPER;
+ retbuf[2] = '\0';
+ sprintf(completion_msg, "kpasswd %s from %s FAILED",
+ "Unknown or Non-Implemented Operation Type!",
+ inet_ntoa(client_server_info.client_name.sin_addr ));
+ syslog(LOG_AUTH | LOG_INFO, completion_msg);
+ retval = 255;
+ goto finish;
+ } /* switch (request_type->oper_code) */
+
+finish:
+ return(retval);
+}
--- /dev/null
+/*
+ * kadmin/server/adm_listen.c
+ *
+ * Copyright 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ *
+ * Network Listen Loop for the Kerberos Version 5 Administration server
+ */
+
+/*
+ * Sandia National Laboratories also makes no representations about the
+ * suitability of the modifications, or additions to this software for
+ * any purpose. It is provided "as is" without express or implied warranty.
+ */
+
+
+/*
+ adm_listen.c
+*/
+
+#ifdef _AIX
+#include <sys/select.h>
+#endif
+
+#include "k5-int.h"
+
+#include <syslog.h>
+#include <signal.h>
+#include "com_err.h"
+
+#ifndef sigmask
+#define sigmask(m) (1 <<((m)-1))
+#endif
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#ifndef hpux
+#include <arpa/inet.h>
+#endif
+
+#include "adm_extern.h"
+
+int adm_debug_flag = 0;
+
+#ifdef USE_SIGPROCMASK
+/* just do it right */
+void
+kill_children()
+{
+ int i;
+ sigset_t old, new;
+
+ sigemptyset(&old);
+ sigemptyset(&new);
+ sigaddset(&new,SIGCHLD);
+ sigprocmask(SIG_BLOCK, &new, &old);
+
+ for (i = 0; i < pidarraysize; i++) {
+ kill(pidarray[i], SIGINT);
+ syslog(LOG_AUTH | LOG_INFO, "Killing Admin Child %d", pidarray[i]);
+ }
+
+ sigprocmask(SIG_SETMASK, &old, NULL);
+}
+
+#else
+
+#ifdef USE_SIGPROCMASK
+/* fake sigmask, sigblock, sigsetmask */
+#include <signal.h>
+#define sigmask(x) (1L<<(x)-1)
+#define sigsetmask(x) sigprocmask(SIG_SETMASK,&x,NULL)
+static int _fake_sigstore;
+#define sigblock(x) (_fake_sigstore=x,sigprocmask(SIG_BLOCK,&_fake_sigstore,0))
+#endif
+
+void
+kill_children()
+{
+ register int i;
+ int osigmask;
+
+ osigmask = sigblock(sigmask(SIGCHLD));
+
+ for (i = 0; i < pidarraysize; i++) {
+ kill(pidarray[i], SIGINT);
+ syslog(LOG_AUTH | LOG_INFO, "Killing Admin Child %d", pidarray[i]);
+ }
+
+ sigsetmask(osigmask);
+ return;
+}
+#endif /* HAVE_SIGSET */
+
+/* adm5_listen_and_process - listen on the admin servers port for a request */
+
+int
+adm5_listen_and_process(context, prog)
+ krb5_context context;
+ const char *prog;
+{
+ extern int errno;
+ int found;
+ fd_set mask, readfds;
+ int addrlen;
+ krb5_error_code process_client();
+ krb5_error_code retval;
+ void kill_children();
+ int pid;
+
+ (void) listen(client_server_info.server_socket, 1);
+
+ FD_ZERO(&mask);
+ FD_SET(client_server_info.server_socket, &mask);
+
+ for (;;) { /* loop nearly forever */
+ if (exit_now) {
+ kill_children();
+ return(0);
+ }
+
+ readfds = mask;
+ if ((found = select(client_server_info.server_socket + 1,
+ &readfds,
+ (fd_set *)0,
+ (fd_set *)0,
+ (struct timeval *)0)) == 0)
+ continue; /* no things read */
+
+ if (found < 0) {
+ if (errno != EINTR)
+ syslog(LOG_AUTH | LOG_INFO,
+ "%s: select: %s", "adm5_listen_and_process",
+ error_message(errno));
+ continue;
+ }
+
+ if (FD_ISSET(client_server_info.server_socket, &readfds)) {
+ /* accept the conn */
+ addrlen = sizeof(client_server_info.client_name);
+ if ((client_server_info.client_socket =
+ accept(client_server_info.server_socket,
+ (struct sockaddr *) &client_server_info.client_name,
+ &addrlen)) < 0) {
+ syslog(LOG_AUTH | LOG_INFO, "%s: accept: %s",
+ "adm5_listen_and_process",
+ error_message(errno));
+ continue;
+ }
+
+ if (adm_debug_flag) {
+ retval = process_client(context,
+ "adm5_listen_and_process");
+ exit(retval);
+ }
+
+ /* if you want a sep daemon for each server */
+ if (!(pid = fork())) {
+ /* child */
+ (void) close(client_server_info.server_socket);
+
+ retval = process_client(context,
+ "adm5_listen_and_process");
+ exit(retval);
+ } else {
+ /* parent */
+ if (pid < 0) {
+ syslog(LOG_AUTH | LOG_INFO, "%s: fork: %s",
+ "adm5_listen_and_process",
+ error_message(errno));
+ (void) close(client_server_info.client_socket);
+ continue;
+ }
+
+ /* fork succeded: keep tabs on child */
+
+ (void) close(client_server_info.client_socket);
+ if (pidarray) {
+ pidarray = (int *) realloc((char *)pidarray,
+ (++pidarraysize) * sizeof(int));
+ pidarray[pidarraysize - 1] = pid;
+ } else {
+ pidarraysize = 1;
+ pidarray =
+ (int *) malloc(pidarraysize *sizeof(int));
+ pidarray[0] = pid;
+ }
+ }
+ } else {
+ syslog(LOG_AUTH | LOG_INFO, "%s: something else woke me up!",
+ "adm5_listen_and_process");
+ return(0);
+ }
+ }
+}
--- /dev/null
+/*
+ * kadmin/server/adm_msgs.c
+ *
+ * Copyright 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ *
+ * Top-level loop of the Kerberos Version 5 Administration server
+ */
+
+/*
+ * Sandia National Laboratories also makes no representations about the
+ * suitability of the modifications, or additions to this software for
+ * any purpose. It is provided "as is" without express or implied warranty.
+ */
+
+
+char *oper_type[] = {
+ "complete", /* 0 */
+ "addition", /* 1 */
+ "deletion", /* 2 */
+ "change", /* 3 */
+ "modification", /* 4 */
+ "inquiry" /* 5 */
+};
+
+char *ksrvutil_message[] = {
+ "Service Key Changed", /* 0 */
+ "New Key and Version Received" /* 1 */
+};
+
+char *kadmind_general_response[] = {
+ "Success", /* 0 */
+ "Service Access Granted" /* 1 */
+};
+
+char *kadmind_kpasswd_response[] = {
+ "Password Changed", /* 0 */
+ "Password NOT Changed!" /* 1 */
+};
+
+char *kadmind_ksrvutil_response[] = {
+ "Service Password Change Complete", /* 0 */
+ "One or More Service Password Change(s) Failed!", /* 1 */
+ "Database Update Failure - Possible Catastrophe!!" /* 2 */
+};
+
+char *kadmind_kadmin_response[] = {
+ "Administrative Service Completed", /* 0 */
+ "Principal Unknown!", /* 1 */
+ "Principal Already Exists!", /* 2 */
+ "Allocation Failure!", /* 3 */
+ "Password Failure!", /* 4 */
+ "Protocol Failure!", /* 5 */
+ "Security Failure!", /* 6 */
+ "Admin Client Not in ACL List!", /* 7 */
+ "Database Update Failure - Possible Catastrophe!!" /* 8 */
+};
--- /dev/null
+/*
+ * kadmin/server/adm_nego.c
+ *
+ * Copyright 1990,1991 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * 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. 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.
+ *
+ * Sandia National Laboratories also makes no representations about the
+ * suitability of the modifications, or additions to this software for
+ * any purpose. It is provided "as is" without express or implied warranty.
+ *
+ * Modify the Kerberos Database
+ */
+
+
+#include "com_err.h"
+#include <sys/types.h>
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#ifndef hpux
+#include <arpa/inet.h>
+#endif
+
+#include <stdio.h>
+
+#include "k5-int.h"
+#include "adm_extern.h"
+
+krb5_error_code
+adm_negotiate_key(context, auth_context, prog, new_passwd)
+ krb5_context context;
+ krb5_auth_context *auth_context;
+ char const * prog;
+ char * new_passwd;
+{
+ krb5_replay_data replaydata;
+ krb5_data msg_data, inbuf;
+ krb5_error_code retval;
+#if defined(MACH_PASS) || defined(SANDIA) /* Machine-generated passwords. */
+ krb5_pwd_data *pwd_data;
+ krb5_pwd_data encodable_data;
+ krb5_data *encoded_pw_string;
+ passwd_phrase_element **next_passwd_phrase_element;
+ char *tmp_passwd, *tmp_phrase;
+ krb5_authenticator *client_auth_data;
+ int count, i, j, k;
+ int legit_passwd = 0;
+#endif
+ extern int errno;
+
+#if defined(MACH_PASS) || defined(SANDIA) /* Machine-generated passwords. */
+
+#define clear_encodable_data() \
+{ encodable_data.sequence_count = 0; \
+ encodable_data.element = 0; \
+}
+
+#define free_seq_list() \
+{ free(encodable_data.element); \
+}
+
+#define free_pwd_and_phrase_structures() \
+{ next_passwd_phrase_element = encodable_data.element; \
+ for (k = 0; \
+ *next_passwd_phrase_element != 0 && k < encodable_data.sequence_count; \
+ k++) { \
+ free(*next_passwd_phrase_element); \
+ *next_passwd_phrase_element = 0; \
+ next_passwd_phrase_element++; } \
+}
+
+#define free_passwds() \
+{ next_passwd_phrase_element = encodable_data.element; \
+ for (k = 0; \
+ *next_passwd_phrase_element != 0 && k < encodable_data.sequence_count; \
+ k++) { \
+ memset((char *) (*next_passwd_phrase_element)->passwd->data, \
+ 0, (*next_passwd_phrase_element)->passwd->length); \
+ free((*next_passwd_phrase_element)->passwd->data); \
+ next_passwd_phrase_element++; } \
+}
+
+#define free_phrases() \
+{ next_passwd_phrase_element = encodable_data.element; \
+ for (k = 0; \
+ *next_passwd_phrase_element != 0 && k < encodable_data.sequence_count; \
+ k++) { \
+ memset((char *) (*next_passwd_phrase_element)->phrase->data, \
+ 0, (*next_passwd_phrase_element)->phrase->length); \
+ free((*next_passwd_phrase_element)->phrase->data); \
+ next_passwd_phrase_element++; } \
+}
+
+ encodable_data.sequence_count =
+ ADM_MAX_PW_CHOICES * ADM_MAX_PW_ITERATIONS;
+
+ /* Allocate List of Password and Phrase Addresses Pointers */
+ if ((encodable_data.element = (passwd_phrase_element **) calloc(
+ encodable_data.sequence_count + 1,
+ sizeof(passwd_phrase_element *))) ==
+ (passwd_phrase_element **) 0) {
+ clear_encodable_data();
+ com_err("adm_negotiate_key", 0,
+ "No Memory for Password and Phrase List");
+ return(1);
+ }
+
+ next_passwd_phrase_element = encodable_data.element;
+
+ /* Allow for ADM_MAX_PW_ITERATIONS Sets of Five Passwords/Phrases */
+ for ( i = 0; i < ADM_MAX_PW_ITERATIONS; i++) {
+ if ( i == ADM_MAX_PW_ITERATIONS ) {
+ com_err("adm_negotiate_key", 0,
+ "Excessive Password List Requests");
+ return(1);
+ }
+
+ /* Allocate passwd_phrase_element structures */
+ for (j = 0; j < ADM_MAX_PW_CHOICES; j++) {
+ if ((*next_passwd_phrase_element =
+ (passwd_phrase_element *) calloc(1,
+ sizeof(passwd_phrase_element))) ==
+ (passwd_phrase_element *) 0) {
+ free_pwd_and_phrase_structures();
+ free_seq_list();
+ clear_encodable_data();
+ com_err("adm_negotiate_key", 0,
+ "No Memory for Additional Password and Phrase Structures");
+ return(1);
+ }
+
+ if ((retval = get_pwd_and_phrase("adm_negotiate_key",
+ &tmp_passwd, &tmp_phrase))) {
+ free_pwd_and_phrase_structures();
+ free_seq_list();
+ clear_encodable_data();
+ com_err("adm_negotiate_key", 0, "Unable to get_pwd_and_phrase");
+ return(1);
+ }
+
+ if (((*next_passwd_phrase_element)->passwd =
+ (krb5_data *) calloc(1,
+ sizeof(krb5_data))) == (krb5_data *) 0) {
+ free_pwd_and_phrase_structures();
+ free_seq_list();
+ clear_encodable_data();
+ com_err("adm_negotiate_key", 0,
+ "No Memory for Additional Password and Phrase Structures");
+ return(1);
+ }
+
+ if (((*next_passwd_phrase_element)->passwd->data =
+ (char *) calloc (1,
+ strlen(tmp_passwd))) == (char *) 0) {
+ free_pwd_and_phrase_structures();
+ free_seq_list();
+ clear_encodable_data();
+ com_err("adm_negotiate_key", ENOMEM,
+ "for Additional Passwords");
+ }
+
+ strcpy((*next_passwd_phrase_element)->passwd->data, tmp_passwd);
+ (*next_passwd_phrase_element)->passwd->length = strlen(tmp_passwd);
+
+ if (((*next_passwd_phrase_element)->phrase =
+ (krb5_data *) calloc(1,
+ sizeof(krb5_data))) == (krb5_data *) 0) {
+ free_pwd_and_phrase_structures();
+ free_seq_list();
+ clear_encodable_data();
+ com_err("adm_negotiate_key", 0,
+ "No Memory for Additional Password and Phrase Structures");
+ return(1);
+ }
+
+ if (((*next_passwd_phrase_element)->phrase->data =
+ (char *) calloc (1,
+ strlen(tmp_phrase))) == (char *) 0) {
+ free_pwd_and_phrase_structures();
+ free_seq_list();
+ clear_encodable_data();
+ com_err("adm_negotiate_key", ENOMEM,
+ "for Additional Passwords");
+ return(1);
+ }
+
+ strcpy((*next_passwd_phrase_element)->phrase->data, tmp_phrase);
+ (*next_passwd_phrase_element)->phrase->length = strlen(tmp_phrase);
+
+ free(tmp_passwd);
+ free(tmp_phrase);
+
+ next_passwd_phrase_element++;
+ }
+ } /* for i <= KADM_MAX_PW_CHOICES */
+
+ /* Asn.1 Encode the Passwords and Phrases */
+ if ((retval = encode_krb5_pwd_data(&encodable_data,
+ &encoded_pw_string))) {
+ com_err("adm_negotiate_key", 0,
+ "Unable to encode Password and Phrase Data");
+ return(1);
+ }
+
+ /* Free Phrases But Hold onto Passwds for Awhile*/
+ free_phrases();
+
+ /* Encrypt Password/Phrases Encoding */
+ retval = krb5_mk_priv(context, auth_context, encoded_pw_string,
+ &msg_data, &replaydata);
+ if (retval ) {
+ free_passwds();
+ free_pwd_and_phrase_structures();
+ free_seq_list();
+ clear_encodable_data();
+ com_err("adm_negotiate_key", retval, "during mk_priv");
+ return(1);
+ }
+
+ /* Send Encrypted/Encoded Passwords and Phrases to Client */
+ if (krb5_write_message(context, &client_server_info.client_socket, &msg_data)){
+ free(msg_data.data);
+ free_passwds();
+ free_pwd_and_phrase_structures();
+ free_seq_list();
+ clear_encodable_data();
+ com_err("adm_negotiate_key", 0, "Error Performing Password Write");
+ return(1);
+ }
+ free(msg_data.data);
+
+#endif /* MACH_PASS - Machine-gen. passwords */
+ /* Read Client Response */
+ if (krb5_read_message(context, &client_server_info.client_socket, &inbuf)){
+#if defined(MACH_PASS) || defined(SANDIA)
+ free_passwds();
+ free_pwd_and_phrase_structures();
+ free_seq_list();
+ clear_encodable_data();
+#endif
+ com_err("adm_negotiate_key", errno, "Error Performing Password Read");
+ return(1);
+ }
+
+ /* Decrypt Client Response */
+ if ((retval = krb5_rd_priv(context, auth_context, &inbuf,
+ &msg_data, &replaydata))) {
+ free(inbuf.data);
+#if defined(MACH_PASS) || defined(SANDIA)
+ free_passwds();
+ free_pwd_and_phrase_structures();
+ free_seq_list();
+ clear_encodable_data();
+#endif
+ com_err("adm_negotiate_key", retval, "krb5_rd_priv error %s",
+ error_message(retval));
+ return(1);
+ }
+ free(inbuf.data);
+
+#if defined(MACH_PASS) || defined(SANDIA) /* Machine-generated passwords */
+ legit_passwd = 0;
+ next_passwd_phrase_element = encodable_data.element;
+ /* Compare Response with Acceptable Passwords */
+ for (j = 0;
+ j < ADM_MAX_PW_CHOICES * ADM_MAX_PW_ITERATIONS;
+ j++) {
+ if ((retval = memcmp(msg_data.data,
+ (*next_passwd_phrase_element)->passwd->data,
+ strlen((*next_passwd_phrase_element)->passwd->data))) == 0) {
+ legit_passwd++;
+ break; /* Exit Loop - Match Found */
+ }
+ next_passwd_phrase_element++;
+ }
+ /* Now Free Passwds */
+ free_passwds();
+
+ /* free password_and_phrase structures */
+ free_pwd_and_phrase_structures();
+
+ /* free passwd_phrase_element list */
+ free_seq_list();
+
+ /* clear krb5_pwd_data */
+ clear_encodable_data();
+
+ if (!(legit_passwd)) {
+ com_err("adm_negotiate_key", 0, "Invalid Password Entered");
+ return(1);
+ }
+#endif
+ strncpy(new_passwd, msg_data.data, msg_data.length);
+ free(msg_data.data);
+
+ return(0);
+}
+
--- /dev/null
+/*
+ * kadmin/server/adm_network.c
+ *
+ * Copyright 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ *
+ * Network Initialization/Shutdown Component of the
+ * Version 5 Administration network
+ */
+
+/*
+ * Sandia National Laboratories also makes no representations about the
+ * suitability of the modifications, or additions to this software for
+ * any purpose. It is provided "as is" without express or implied warranty.
+ */
+
+
+/*
+ * adm_network.c
+ */
+
+#include <stdio.h>
+#include "com_err.h"
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/param.h>
+#include <signal.h>
+
+#ifndef sigmask
+#define sigmask(m) (1 <<((m)-1))
+#endif
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#ifndef hpux
+#include <arpa/inet.h>
+#endif
+#include <netdb.h>
+
+#include "k5-int.h"
+#include "adm_extern.h"
+
+extern int errno;
+
+#ifdef POSIX_SIGTYPE
+#define SIGNAL_RETURN return
+#else
+#define SIGNAL_RETURN return(0)
+#endif
+
+krb5_error_code
+closedown_network(prog)
+const char *prog;
+{
+ if (client_server_info.server_socket == -1) return(1);
+
+ (void) close(client_server_info.server_socket);
+ client_server_info.server_socket = -1;
+ return(0);
+}
+
+krb5_sigtype
+doexit()
+{
+ exit_now = 1;
+ SIGNAL_RETURN;
+}
+
+/*
+ * SIGCHLD brings us here
+ */
+krb5_sigtype
+do_child()
+{
+ /*
+ * <sys/param.h> has been included, so BSD will be defined on
+ * BSD systems
+ */
+#if BSD > 0 && BSD <= 43
+#ifndef WEXITSTATUS
+#define WEXITSTATUS(w) (w).w_retcode
+#define WTERMSIG(w) (w).w_termsig
+#endif
+ union wait status;
+#else
+ int status;
+#endif
+ int pid, i, j;
+
+ signal(SIGCHLD, do_child);
+
+ pid = wait(&status);
+ if (pid < 0)
+ SIGNAL_RETURN;
+
+ for (i = 0; i < pidarraysize; i++)
+ if (pidarray[i] == pid) {
+ /* found it */
+ for (j = i; j < pidarraysize-1; j++)
+ /* copy others down */
+ pidarray[j] = pidarray[j+1];
+ pidarraysize--;
+ if ( !WIFEXITED(status) ) {
+ com_err("adm_network", 0, "child %d: termsig %d",
+ pid, WTERMSIG(status) );
+ com_err("adm_network", 0, "retcode %d",
+ WEXITSTATUS(status));
+ }
+
+ SIGNAL_RETURN;
+ }
+
+ com_err("adm_network", 0,
+ "child %d not in list: termsig %d, retcode %d", pid,
+ WTERMSIG(status), WEXITSTATUS(status));
+
+ SIGNAL_RETURN;
+}
+
+krb5_error_code
+setup_network(context, prog)
+ krb5_context context;
+ const char *prog;
+{
+ krb5_error_code retval;
+ char server_host_name[MAXHOSTNAMELEN];
+ krb5_sigtype doexit(), do_child();
+ struct servent *service_servent;
+ struct hostent *service_hostent;
+
+ signal(SIGINT, doexit);
+ signal(SIGTERM, doexit);
+ signal(SIGHUP, doexit);
+ signal(SIGQUIT, doexit);
+ signal(SIGPIPE, SIG_IGN); /* get errors on write() */
+ signal(SIGALRM, doexit);
+ signal(SIGCHLD, do_child);
+
+ client_server_info.name_of_service = malloc(768);
+ if (!client_server_info.name_of_service) {
+ com_err("setup_network", 0,
+ "adm_network: No Memory for name_of_service");
+ return ENOMEM;
+ }
+
+ (void) sprintf(client_server_info.name_of_service, "%s%s%s%s%s",
+ CPWNAME, "/", realm, "@", realm);
+
+#ifdef DEBUG
+ fprintf(stderr, "client_server_info.name_of_service = %s\n",
+ client_server_info.name_of_service);
+#endif /* DEBUG */
+
+ if ((retval = krb5_parse_name(context, client_server_info.name_of_service,
+ &client_server_info.server))) {
+ free(client_server_info.name_of_service);
+ com_err( "setup_network", retval,
+ "adm_network: Unable to Parse Server Name");
+ return retval;
+ }
+
+ if (gethostname(server_host_name, sizeof(server_host_name))) {
+ retval = errno;
+ krb5_free_principal(context, client_server_info.server);
+ free(client_server_info.name_of_service);
+ com_err( "setup_network", retval,
+ "adm_network: Unable to Identify Who I am");
+ return retval;
+ }
+
+ service_hostent = gethostbyname(server_host_name);
+ if (!service_hostent) {
+ retval = errno;
+ free(client_server_info.name_of_service);
+ com_err("setup_network", retval, "adm_network: Failed gethostname");
+ return retval;
+ }
+
+#ifdef DEBUG
+ fprintf(stderr, "Official host name = %s\n", service_hostent->h_name);
+#endif /* DEBUG */
+
+ client_server_info.server_name.sin_family = AF_INET;
+
+#ifdef unicos61
+ memcpy((char *) &client_server_info.server_name.sin_addr,
+ (char *) service_hostent->h_addr, service_hostent->h_length);
+#else
+ memcpy((char *) &client_server_info.server_name.sin_addr.s_addr,
+ (char *) service_hostent->h_addr, service_hostent->h_length);
+#endif /* unicos61 */
+
+ client_server_info.server_socket = -1;
+
+#ifdef DEBUG
+ fprintf(stderr, "adm5_tcp_portname = %s\n", adm5_tcp_portname);
+#endif /* DEBUG */
+
+ service_servent = getservbyname(adm5_tcp_portname, "tcp");
+ if (admin_port) {
+ client_server_info.server_name.sin_port = admin_port;
+ } else if (service_servent) {
+ client_server_info.server_name.sin_port = service_servent->s_port;
+#ifdef DEBUG
+ fprintf(stderr, "Official service name = %s\n", service_servent->s_name);
+#endif /* DEBUG */
+ } else {
+#ifdef ADM5_DEFAULT_PORT
+ client_server_info.server_name.sin_port = htons(ADM5_DEFAULT_PORT);
+ com_err("setup_network", 0, "adm_network: using default port %d",
+ ADM5_DEFAULT_PORT);
+#else
+ krb5_free_principal(client_server_info.server);
+ free(client_server_info.name_of_service);
+ com_err("setup_network", 0, "adm_network: %s/tcp service unknown",
+ adm5_tcp_portname);
+ return(1);
+#endif
+ }
+
+
+ if ((client_server_info.server_socket =
+ socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+ retval = errno;
+ krb5_free_principal(context, client_server_info.server);
+ free(client_server_info.name_of_service);
+ com_err("setup_network", retval,
+ "adm_network: Cannot create server socket.");
+ return(1);
+ }
+
+#ifdef DEBUG
+ fprintf(stderr, "Socket File Descriptor = %d\n",
+ client_server_info.server_socket);
+ fprintf(stderr, "sin_family = %d\n",
+ client_server_info.server_name.sin_family);
+ fprintf(stderr, "sin_port = %d\n",
+ client_server_info.server_name.sin_port);
+ fprintf(stderr, "in_addr.s_addr = %s\n",
+ inet_ntoa( client_server_info.server_name.sin_addr ));
+#endif /* DEBUG */
+
+ if (bind(client_server_info.server_socket,
+ &client_server_info.server_name,
+ sizeof(client_server_info.server_name)) < 0) {
+ retval = errno;
+ krb5_free_principal(context, client_server_info.server);
+ free(client_server_info.name_of_service);
+ com_err("setup_network", retval,
+ "adm_network: Cannot bind server socket.");
+ return(1);
+ }
+
+ return(0);
+}
--- /dev/null
+#ifdef SANDIA
+/*
+ * kadmin/server/adm_parse.c
+ *
+ * Copyright 1990,1991 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * 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. 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.
+ *
+ * Sandia National Laboratories also makes no representations about the
+ * suitability of the modifications, or additions to this software for
+ * any purpose. It is provided "as is" without express or implied warranty.
+ *
+ * Edit a KDC database.
+ */
+
+#include <syslog.h>
+#include <stdio.h>
+
+#if defined (unicos61) || (defined(mips) && defined(SYSTYPE_BSD43)) || defined(sysvimp)
+#include <time.h>
+#else
+#include <sys/time.h>
+#endif /* unicos61 */
+#if defined(aux20)
+#include <time.h>
+#endif /* aux20 */
+
+#include "k5-int.h"
+
+void
+kadmin_parse_and_set(input_string)
+char *input_string;
+{
+ extern int classification;
+ extern krb5_kvno KDB5_VERSION_NUM;
+ extern krb5_deltat KDB5_MAX_TKT_LIFE;
+ extern krb5_deltat KDB5_MAX_REN_LIFE;
+ extern krb5_timestamp KDB5_EXP_DATE;
+ extern krb5_flags NEW_ATTRIBUTES;
+
+ int num_args;
+ char parameter[40];
+ char first_token[40];
+ char second_token[40];
+
+ int bypass = 0;
+
+ struct tm exp_date;
+ long todays_date;
+ int year;
+ int month;
+ int mday;
+
+ first_token[0] = second_token[0] = '\0';
+ num_args = sscanf(input_string, "%s %s %s", parameter,
+ first_token, second_token);
+
+ if (strcmp(parameter, "BYPASS") == 0) {
+ bypass++;
+ syslog(LOG_ERR,
+ "CAUTION: Classified and Unclassified Principals will be allowed");
+ return;
+ }
+
+ if (strcmp(parameter, "CLASSIFICATION") == 0) {
+ if (strcmp(first_token, "CLASS") == 0) {
+ classification = 1;
+ if (bypass) classification = 0;
+ }
+ return;
+ }
+
+ if (strcmp(parameter, "VERSION_NUM") == 0) {
+ if (num_args < 2) {
+ KDB5_VERSION_NUM = 1;
+ } else {
+ KDB5_VERSION_NUM = atoi(first_token);
+ }
+ return;
+ }
+
+ if (strcmp(parameter, "MAX_TKT_LIFE") == 0) {
+ if (num_args < 2) {
+ KDB5_MAX_TKT_LIFE = KRB5_KDB_MAX_LIFE;
+ } else {
+ switch (second_token[0]) {
+ case 's':
+ KDB5_MAX_TKT_LIFE = atoi(first_token);
+ break;
+ case 'm':
+ KDB5_MAX_TKT_LIFE = atoi(first_token) * 60;
+ break;
+ case 'h':
+ KDB5_MAX_TKT_LIFE = atoi(first_token) * 3600;
+ break;
+ case 'd':
+ KDB5_MAX_TKT_LIFE = atoi(first_token) * 86400;
+ break;
+ case 'w':
+ KDB5_MAX_TKT_LIFE = atoi(first_token) * 604800;
+ break;
+ case 'M': /* 30 days */
+ KDB5_MAX_TKT_LIFE = atoi(first_token) * 18144000;
+ break;
+ case 'y': /* 365 days */
+ KDB5_MAX_TKT_LIFE = atoi(first_token) * 220752000;
+ break;
+ case 'e': /* eternity */
+ KDB5_MAX_TKT_LIFE = 2145830400;
+ break;
+ default:
+ break;
+ }
+ }
+ return;
+ }
+
+ if (strcmp(parameter, "MAX_REN_LIFE") == 0) {
+ if (num_args < 2) {
+ KDB5_MAX_REN_LIFE = KRB5_KDB_MAX_RLIFE;
+ } else {
+ switch (second_token[0]) {
+ case 's':
+ KDB5_MAX_REN_LIFE = atoi(first_token);
+ break;
+ case 'm':
+ KDB5_MAX_REN_LIFE = atoi(first_token) * 60;
+ break;
+ case 'h':
+ KDB5_MAX_REN_LIFE = atoi(first_token) * 3600;
+ break;
+ case 'd':
+ KDB5_MAX_REN_LIFE = atoi(first_token) * 86400;
+ break;
+ case 'w':
+ KDB5_MAX_REN_LIFE = atoi(first_token) * 604800;
+ break;
+ case 'M': /* 30 days */
+ KDB5_MAX_REN_LIFE = atoi(first_token) * 18144000;
+ break;
+ case 'y': /* 365 days */
+ KDB5_MAX_REN_LIFE = atoi(first_token) * 220752000;
+ break;
+ case 'e': /* eternity */
+ KDB5_MAX_REN_LIFE = 2145830400;
+ break;
+ default:
+ break;
+ }
+ }
+ return;
+ }
+
+
+ if (strcmp(parameter, "SET_EXP_DATE") == 0) {
+ (void) time(&todays_date);
+ switch (first_token[0]) {
+ case 'e': /* eternity */
+ KDB5_EXP_DATE = 2145830400;
+ year = 2037;
+ month = 12;
+ mday = 30;
+ sprintf(first_token, "%s", "eternity");
+ break;
+ case 'y': /* yesterday */
+ KDB5_EXP_DATE = todays_date - 86400;
+ year = 1970;
+ month = 01;
+ mday = 01;
+ sprintf(first_token, "%s", "yesterday");
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '9':
+ sscanf(first_token, "%d/%d/%d", &year, &month, &mday);
+ year = (year > 1900) ? year - 1900 : year;
+ year = (year > 137) ? year - 100 : year;
+ year = (year > 137) ? 137 : year;
+ exp_date.tm_year =
+ ((year >= 00 && year < 38) ||
+ (year >= 70 && year <= 138)) ? year : 137;
+ exp_date.tm_mon =
+ (month >= 1 &&
+ month <= 12) ? month - 1 : 0;
+ exp_date.tm_mday =
+ (mday >= 1 &&
+ mday <= 31) ? mday : 1;
+ exp_date.tm_hour = 0;
+ exp_date.tm_min = 1;
+ exp_date.tm_sec = 0;
+ KDB5_EXP_DATE = convert_tm_to_sec(&exp_date);
+ break;
+ default:
+ KDB5_EXP_DATE = KRB5_KDB_EXPIRATION;
+ sprintf(first_token, "%s", "Default KDB Expiration");
+ break;
+ }
+ if (year < 1900) year += 1900;
+ if (year < 1938) year += 100;
+ return;
+ }
+
+ if (strcmp(parameter, "SET_PWCHG") == 0) {
+ if (num_args < 2) {
+ NEW_ATTRIBUTES = NEW_ATTRIBUTES | KRB5_KDB_REQUIRES_PWCHANGE;
+ } else {
+ if (first_token[0] == 'y' || first_token[0] == 'Y') {
+ NEW_ATTRIBUTES = NEW_ATTRIBUTES | KRB5_KDB_REQUIRES_PWCHANGE;
+ } else {
+ NEW_ATTRIBUTES = NEW_ATTRIBUTES & ~KRB5_KDB_REQUIRES_PWCHANGE;
+ KDB5_VERSION_NUM = 1;
+ }
+ }
+ return;
+ }
+
+ if (strcmp(parameter, "SET_PREAUTH") == 0) {
+ if (num_args < 2) {
+ NEW_ATTRIBUTES = NEW_ATTRIBUTES | KRB5_KDB_REQUIRES_PRE_AUTH;
+ } else {
+ if (first_token[0] == 'y' || first_token[0] == 'Y') {
+ NEW_ATTRIBUTES = NEW_ATTRIBUTES | KRB5_KDB_REQUIRES_PRE_AUTH;
+ } else {
+ NEW_ATTRIBUTES = NEW_ATTRIBUTES & ~KRB5_KDB_REQUIRES_PRE_AUTH;
+ }
+ }
+ return;
+ }
+
+ if (strcmp(parameter, "SET_SECUREID") == 0) {
+ if (num_args < 2) {
+ NEW_ATTRIBUTES = NEW_ATTRIBUTES | KRB5_KDB_REQUIRES_HW_AUTH |
+ KRB5_KDB_REQUIRES_PRE_AUTH;
+ } else {
+ if (first_token[0] == 'y' || first_token[0] == 'Y') {
+ NEW_ATTRIBUTES = NEW_ATTRIBUTES | KRB5_KDB_REQUIRES_HW_AUTH |
+ KRB5_KDB_REQUIRES_PRE_AUTH;
+ } else {
+ NEW_ATTRIBUTES = NEW_ATTRIBUTES & ~KRB5_KDB_REQUIRES_HW_AUTH;
+ }
+ }
+ return;
+ }
+}
+#endif
--- /dev/null
+/*
+ * kadmin/server/adm_process.c
+ *
+ * Copyright 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ *
+ */
+
+/*
+ * Sandia National Laboratories also makes no representations about the
+ * suitability of the modifications, or additions to this software for
+ * any purpose. It is provided "as is" without express or implied warranty.
+ */
+
+
+/*
+ adm_process.c
+*/
+
+#include <sys/types.h>
+#include <syslog.h>
+#include <sys/wait.h>
+#include <stdio.h>
+#include "com_err.h"
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#ifndef hpux
+#include <arpa/inet.h>
+#endif
+
+#include "k5-int.h"
+#include "adm_extern.h"
+
+extern krb5_encrypt_block master_encblock;
+extern krb5_keyblock master_keyblock;
+
+static krb5_error_code
+cpw_keyproc(context, keyblock)
+ krb5_context context;
+ krb5_keyblock ** keyblock;
+{
+ krb5_error_code retval;
+ krb5_db_entry cpw_entry;
+ krb5_principal cpw_krb;
+ krb5_keyblock *realkey;
+ krb5_boolean more;
+ int nprincs = 1;
+
+ if (*keyblock == NULL) {
+ if (retval = krb5_parse_name(context,
+ client_server_info.name_of_service,
+ &cpw_krb)) {
+ syslog(LOG_ERR,
+ "cpw_keyproc %d while attempting to parse \"%s\"",
+ client_server_info.name_of_service, retval);
+ return(retval);
+ }
+
+ if (retval = krb5_db_get_principal(context, cpw_krb, &cpw_entry,
+ &nprincs, &more)) {
+ syslog(LOG_ERR,
+ "cpw_keyproc %d while extracting %s entry",
+ client_server_info.name_of_service, retval);
+ return(retval);
+ }
+
+ if (!nprincs) return(0);
+
+ if ((realkey = (krb5_keyblock *) calloc (1,
+ sizeof(krb5_keyblock))) == (krb5_keyblock * ) 0) {
+ krb5_db_free_principal(context, &cpw_entry, nprincs);
+ syslog(LOG_ERR, "cpw_keyproc: No Memory for server key");
+ close(client_server_info.client_socket);
+ return(ENOMEM);
+ }
+
+ /* Extract the real kadmin/<realm> keyblock */
+ if (retval = krb5_kdb_decrypt_key(context,
+ &master_encblock,
+ &cpw_entry.key,
+ realkey)) {
+ krb5_db_free_principal(context, &cpw_entry, nprincs);
+ free(realkey);
+ syslog(LOG_ERR,
+ "cpw_keyproc: Cannot extract %s from master key",
+ client_server_info.name_of_service);
+ exit(retval);
+ }
+
+ *keyblock = realkey;
+ }
+ return(0);
+}
+
+krb5_error_code
+process_client(context, prog)
+ krb5_context context;
+ char *prog;
+{
+ krb5_error_code retval;
+
+ krb5_keyblock * cpw_keyblock = NULL;
+
+ int on = 1;
+ krb5_db_entry server_entry;
+
+ char retbuf[512];
+
+ krb5_data final_msg;
+ char completion_msg[520];
+ kadmin_requests request_type;
+ krb5_auth_context *auth_context = NULL;
+ krb5_ticket * client_ticket = NULL;
+ krb5_replay_data replaydata;
+
+ int number_of_entries;
+ krb5_boolean more;
+ int namelen;
+
+ char *req_type = "";
+ int otype;
+
+ u_short data_len;
+ krb5_data outbuf;
+ krb5_data inbuf, msg_data;
+ extern int errno;
+
+ krb5_timestamp adm_time;
+
+ outbuf.data = retbuf;
+ if (setsockopt(client_server_info.client_socket,
+ SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)) < 0) {
+ syslog(LOG_ERR, "adm_process: setsockopt keepalive: %d", errno);
+ }
+
+ /* V4 kpasswd Protocol Hack */
+ /* Read Length of Data */
+ retval = krb5_net_read(context, client_server_info.client_socket,
+ (char *) &data_len, 2);
+ if (retval < 0) {
+ syslog(LOG_ERR, "kadmind error: net_read Length Failure");
+ (void) sprintf(retbuf, "kadmind error during net_read for Length\n");
+ exit(0);
+ }
+
+ if (retval = krb5_db_init(context)) { /* Open as client */
+ syslog(LOG_ERR, "adm_process: Can't Open Database");
+ close(client_server_info.client_socket);
+ exit(0);
+ }
+
+/* Get Server Credentials for Mutual Authentication and Private
+ * Messages Note: Here client is the kadmin/<realm> server
+ */
+ number_of_entries = 1;
+ if ((retval = krb5_db_get_principal(context, client_server_info.server,
+ &server_entry,
+ &number_of_entries,
+ &more))) {
+ syslog(LOG_ERR,
+ "kadmind error: krb5_db_get_principal error: %d", retval);
+ close(client_server_info.client_socket);
+ exit(0);
+ }
+
+ if (more) {
+ krb5_db_free_principal(context, &server_entry, number_of_entries);
+ syslog(LOG_ERR, "kadmind error: kadmin/<realm> service not unique");
+ exit(1);
+ }
+
+ if (number_of_entries != 1) {
+ krb5_db_free_principal(context, &server_entry, number_of_entries);
+ syslog(LOG_ERR, "kadmind error: kadmin/<realm> service UNKNOWN");
+ close(client_server_info.client_socket);
+ exit(0);
+ }
+
+ if ((cpw_keyblock = (krb5_keyblock *) calloc (1,
+ sizeof(krb5_keyblock))) == (krb5_keyblock *) 0) {
+ krb5_db_free_principal(context, &server_entry, number_of_entries);
+ syslog(LOG_ERR,
+ "kadmind error: No Memory for server key");
+ close(client_server_info.client_socket);
+ exit(0);
+ }
+
+ /* Extract the real kadmin/<realm> keyblock */
+ if (retval = krb5_kdb_decrypt_key(context,
+ &master_encblock,
+ &server_entry.key,
+ cpw_keyblock)) {
+ krb5_db_free_principal(context, &server_entry, number_of_entries);
+ free(cpw_keyblock);
+ syslog(LOG_ERR,
+ "kadmind error: Cannot extract kadmin/<realm> from master key");
+ close(client_server_info.client_socket);
+ exit(0);
+ }
+
+/*
+ * To verify authenticity, we need to know the address of the
+ * client.
+ */
+
+ namelen = sizeof(client_server_info.client_addr);
+ if (getpeername(client_server_info.client_socket,
+ (struct sockaddr *) &client_server_info.client_addr,
+ &namelen) < 0) {
+ syslog(LOG_ERR, "kadmind error: Unable to Obtain Client Name.");
+ close(client_server_info.client_socket);
+ exit(0);
+ }
+
+ /* we use mutual authentication */
+ client_server_info.client_addr.addrtype =
+ client_server_info.client_name.sin_family;
+ client_server_info.client_addr.length = SIZEOF_INADDR;
+ client_server_info.client_addr.contents =
+ (krb5_octet *) &client_server_info.client_name.sin_addr;
+
+ client_server_info.server_addr.addrtype =
+ client_server_info.server_name.sin_family;
+ client_server_info.server_addr.length = SIZEOF_INADDR;
+ client_server_info.server_addr.contents =
+ (krb5_octet *) &client_server_info.server_name.sin_addr;
+
+ krb5_init_ets(context);
+
+ syslog(LOG_AUTH | LOG_INFO,
+ "Request for Administrative Service Received from %s - Authenticating.",
+ inet_ntoa( client_server_info.client_name.sin_addr ));
+
+ cpw_keyproc(context, &cpw_keyblock);
+
+ if (krb5_auth_con_init(context, &auth_context))
+ exit(1);
+
+ krb5_auth_con_setflags(context,auth_context,KRB5_AUTH_CONTEXT_RET_SEQUENCE);
+
+ krb5_auth_con_setaddrs(context, auth_context,
+ &client_server_info.server_addr,
+ &client_server_info.client_addr);
+
+ if (krb5_auth_con_setuseruserkey(context, auth_context, cpw_keyblock))
+ exit(1);
+
+ if ((retval = krb5_recvauth(context, &auth_context,
+ (krb5_pointer) &client_server_info.client_socket,
+ ADM5_CPW_VERSION,
+ client_server_info.server,
+ NULL,
+ 0,
+ NULL,
+ &client_ticket
+ ))) {
+ syslog(LOG_ERR, "kadmind error: %s during recvauth\n",
+ error_message(retval));
+ (void) sprintf(retbuf, "kadmind error during recvauth: %s\n",
+ error_message(retval));
+ krb5_free_keyblock(context, cpw_keyblock);
+ goto finish;
+ }
+ krb5_free_keyblock(context, cpw_keyblock);
+
+ if (retval = krb5_copy_principal(context, client_ticket->enc_part2->client,
+ &client_server_info.client))
+ goto finish;
+
+ /* Check if ticket was issued using password (and not tgt)
+ * within the last 5 minutes
+ */
+
+ if (!(client_ticket->enc_part2->flags & TKT_FLG_INITIAL)) {
+ syslog(LOG_ERR, "Client ticket not initial");
+ close(client_server_info.client_socket);
+ exit(0);
+ }
+
+ if (retval = krb5_timeofday(context, &adm_time)) {
+ syslog(LOG_ERR, "Can't get time of day");
+ close(client_server_info.client_socket);
+ exit(0);
+ }
+
+ if ((adm_time - client_ticket->enc_part2->times.authtime) > 60*5) {
+ syslog(LOG_ERR, "Client ticket not recent");
+ close(client_server_info.client_socket);
+ exit(0);
+ }
+
+ if ((client_server_info.name_of_client =
+ (char *) calloc (1, 3 * 255)) == (char *) 0) {
+ syslog(LOG_ERR, "kadmind error: No Memory for name_of_client");
+ close(client_server_info.client_socket);
+ exit(0);
+ }
+
+ if ((retval = krb5_unparse_name(context, client_server_info.client,
+ &client_server_info.name_of_client))) {
+ syslog(LOG_ERR, "kadmind error: unparse failed.",
+ error_message(retval));
+ goto finish;
+ }
+
+ syslog(LOG_AUTH | LOG_INFO,
+ "Request for Administrative Service Received from %s at %s.",
+ client_server_info.name_of_client,
+ inet_ntoa( client_server_info.client_name.sin_addr ));
+
+ /* compose the reply */
+ outbuf.data[0] = KADMIND;
+ outbuf.data[1] = KADMSAG;
+ outbuf.length = 2;
+
+ /* write back the response */
+ if ((retval = krb5_write_message(context, &client_server_info.client_socket,
+ &outbuf))){
+ syslog(LOG_ERR, "kadmind error: Write Message Failure: %s",
+ error_message(retval));
+ retval = 1;
+ goto finish;
+ }
+
+ /* Ok Now let's get the first private message and respond */
+ if (retval = krb5_read_message(context, &client_server_info.client_socket,
+ &inbuf)){
+ syslog(LOG_ERR, "kadmind error: read First Message Failure: %s",
+ error_message(retval));
+ retval = 1;
+ goto finish;
+ }
+
+ if ((retval = krb5_rd_priv(context, auth_context, &inbuf,
+ &msg_data, &replaydata))) {
+ free(inbuf.data);
+ syslog(LOG_ERR, "kadmind error: rd_priv:%s\n", error_message(retval));
+ goto finish;
+ }
+ free(inbuf.data);
+
+ request_type.appl_code = msg_data.data[0];
+ request_type.oper_code = msg_data.data[1];
+
+ free(msg_data.data);
+
+ switch (request_type.appl_code) {
+ case KPASSWD:
+ req_type = "kpasswd";
+ if (retval = adm5_kpasswd(context, auth_context, "process_client",
+ &request_type, retbuf, &otype)) {
+ goto finish;
+ }
+ break;
+
+ case KADMIN:
+ req_type = "kadmin";
+ if (retval = adm5_kadmin(context, auth_context, "process_client",
+ retbuf, &otype)) {
+ goto finish;
+ }
+ retbuf[0] = KADMIN;
+ retbuf[2] = KADMGOOD;
+ retbuf[3] = '\0';
+ otype = 0;
+ break;
+
+
+ default:
+ retbuf[0] = KUNKNOWNAPPL;
+ retbuf[1] = '\0';
+ sprintf(completion_msg, "%s from %s (%02x) FAILED",
+ "Unknown Application Type!",
+ inet_ntoa(client_server_info.client_name.sin_addr),
+ request_type.appl_code);
+ /* Service Not Supported */
+ retval = 255;
+ syslog(LOG_AUTH | LOG_INFO, completion_msg);
+ goto finish;
+ } /* switch(request_type.appl_code) */
+
+ if ((final_msg.data = (char *) calloc(1,10)) == (char *) 0) {
+ syslog(LOG_ERR | LOG_INFO, "no Memory while allocating final_msg.data");
+ return ENOMEM;
+ }
+ final_msg.data = retbuf;
+ final_msg.length = strlen(retbuf) + 1;
+
+ /* Send Completion Message */
+ if (retval = krb5_mk_priv(context, auth_context, &final_msg,
+ &msg_data, &replaydata)) {
+ syslog(LOG_ERR, "kadmind error Error Performing Final mk_priv");
+ goto finish;
+ }
+
+ /* Send Final Reply to Client */
+ if (retval = krb5_write_message(context, &client_server_info.client_socket,
+ &msg_data)){
+ free(msg_data.data);
+ syslog(LOG_ERR, "Error Performing Final Write: %s",
+ error_message(retval));
+ retval = 1;
+ goto finish;
+ }
+ free(msg_data.data);
+
+finish:
+
+ if (retval) {
+ free (client_server_info.name_of_client);
+ close(client_server_info.client_socket);
+ exit(1);
+ }
+
+ sprintf(completion_msg,
+ "%s %s for %s at %s - Completed Successfully",
+ req_type,
+ oper_type[otype],
+ client_server_info.name_of_client,
+ inet_ntoa( client_server_info.client_name.sin_addr ));
+ syslog(LOG_AUTH | LOG_INFO, completion_msg);
+ free (client_server_info.name_of_client);
+ close(client_server_info.client_socket);
+ return 0;
+}
--- /dev/null
+/*
+ * kadmin/server/adm_server.c
+ *
+ * Copyright 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ *
+ * Top-level loop of the Kerberos Version 5 Administration server
+ */
+
+/*
+ * Sandia National Laboratories also makes no representations about the
+ * suitability of the modifications, or additions to this software for
+ * any purpose. It is provided "as is" without express or implied warranty.
+ */
+
+
+/*
+ adm_server.c
+ this holds the main loop and initialization and cleanup code for the server
+*/
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <syslog.h>
+#include <string.h>
+#include "com_err.h"
+
+#include <signal.h>
+#ifndef sigmask
+#define sigmask(m) (1 <<((m)-1))
+#endif
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#ifndef hpux
+#include <arpa/inet.h>
+#endif
+
+#ifndef __STDC__
+#include <varargs.h>
+#endif
+
+#include "k5-int.h"
+#include "adm_extern.h"
+
+char prog[32];
+char *progname = prog;
+char *acl_file_name = DEFAULT_ADMIN_ACL;
+char *adm5_ver_str = ADM5_VERSTR;
+int adm5_ver_len;
+
+char *adm5_tcp_portname = ADM5_PORTNAME;
+int adm5_tcp_port_fd = -1;
+
+unsigned pidarraysize = 0;
+int *pidarray = (int *) 0;
+
+int exit_now = 0;
+
+global_client_server_info client_server_info;
+
+#ifdef SANDIA
+int classification; /* default = Unclassified */
+#endif
+
+krb5_db_entry master_entry;
+
+krb5_flags NEW_ATTRIBUTES;
+
+cleanexit(context, val)
+ krb5_context context;
+ int val;
+{
+ (void) krb5_db_fini(context);
+ exit(val);
+}
+
+krb5_error_code
+closedown_db(context)
+ krb5_context context;
+{
+ krb5_error_code retval;
+
+ /* clean up master key stuff */
+ retval = krb5_finish_key(context, &master_encblock);
+
+ memset((char *)&master_encblock, 0, sizeof(master_encblock));
+ memset((char *)tgs_key.contents, 0, tgs_key.length);
+
+ /* close database */
+ if (retval) {
+ (void) krb5_db_fini(context);
+ return(retval);
+ } else
+ return(krb5_db_fini(context));
+}
+
+void
+usage(name)
+char *name;
+{
+ fprintf(stderr, "Usage: %s\t[-a aclfile] [-d dbname] [-k masterkeytype]",
+ name);
+ fprintf(stderr, "\n\t[-h] [-m] [-M masterkeyname] [-r realm] [-p port]\n");
+ return;
+}
+
+krb5_error_code
+process_args(context, argc, argv)
+ krb5_context context;
+ int argc;
+ char **argv;
+{
+ krb5_error_code retval;
+ int c;
+ krb5_boolean manual = FALSE;
+ int keytypedone = 0;
+ char *mkey_name = 0;
+ char *local_realm;
+ krb5_enctype etype;
+ krb5_enctype kdc_etype = DEFAULT_KDC_ETYPE;
+
+#ifdef SANDIA
+ char input_string[80];
+ FILE *startup_file;
+#endif
+
+ extern char *optarg;
+
+#ifdef SANDIA
+ classification = 0;
+
+ if ((startup_file =
+ fopen(DEFAULT_KDCPARM_NAME, "r")) == (FILE *) 0) {
+ syslog(LOG_ERR,
+ "Cannot open parameter file (%s) - Using default parameters",
+ DEFAULT_KDCPARM_NAME);
+ syslog(LOG_ERR, "Only Unclassified Principals will be allowed");
+ } else {
+ for ( ;; ) {
+ if ((fgets(input_string, sizeof(input_string), startup_file)) == NULL)
+ break;
+ kadmin_parse_and_set(input_string);
+ }
+ fclose(startup_file);
+ }
+#endif
+ while ((c = getopt(argc, argv, "hmM:a:d:k:r:De:p:")) != EOF) {
+ switch(c) {
+ case 'a': /* new acl directory */
+ acl_file_name = optarg;
+ break;
+
+ case 'd':
+ /* put code to deal with alt database place */
+ dbm_db_name = optarg;
+ if (retval = krb5_dbm_db_set_name(context, dbm_db_name)) {
+ fprintf(stderr, "opening database %s: %s",
+ dbm_db_name, error_message(retval));
+ exit(1);
+ }
+ break;
+
+ case 'e':
+ kdc_etype = atoi(optarg);
+ break;
+
+ case 'k': /* keytype for master key */
+ master_keyblock.keytype = atoi(optarg);
+ keytypedone++;
+ break;
+
+ case 'm': /* manual type-in of master key */
+ manual = TRUE;
+ break;
+
+ case 'M': /* master key name in DB */
+ mkey_name = optarg;
+ break;
+
+ case 'r':
+ realm = optarg;
+ break;
+
+ case 'D':
+ adm_debug_flag = 1;
+ break;
+
+ case 'p':
+ admin_port = htons(atoi(optarg));
+ break;
+
+ case 'h': /* get help on using adm_server */
+ default:
+ usage(argv[0]);
+ exit(1); /* Failure - Exit */
+ }
+
+ }
+
+ if (!realm) {
+ /* no realm specified, use default realm */
+ if (retval = krb5_get_default_realm(context, &local_realm)) {
+ com_err(argv[0], retval,
+ "while attempting to retrieve default realm");
+ exit(1);
+ }
+ realm = local_realm;
+ }
+
+ if (!mkey_name) {
+ mkey_name = KRB5_KDB_M_NAME;
+ }
+
+ if (!keytypedone) {
+ master_keyblock.keytype = KEYTYPE_DES;
+ }
+
+ /* assemble & parse the master key name */
+ if (retval = krb5_db_setup_mkey_name(context, mkey_name,
+ realm,
+ (char **) 0,
+ &master_princ)) {
+ com_err(argv[0], retval, "while setting up master key name");
+ exit(1);
+ }
+
+ if (!valid_etype(kdc_etype)) {
+ com_err(argv[0], KRB5_PROG_ETYPE_NOSUPP,
+ "while setting up etype %d", kdc_etype);
+ exit(1);
+ }
+ krb5_use_cstype(context, &master_encblock, kdc_etype);
+
+ if (retval = krb5_db_fetch_mkey(context,
+ master_princ,
+ &master_encblock,
+ manual,
+ FALSE, /* only read it once, if at all */
+ 0, /* No salt supplied */
+ &master_keyblock)) {
+ com_err(argv[0], retval, "while fetching master key");
+ exit(1);
+ }
+
+ /* initialize random key generators */
+ for (etype = 0; etype <= krb5_max_cryptosystem; etype++) {
+ if (krb5_csarray[etype]) {
+ if (retval = (*krb5_csarray[etype]->system->
+ init_random_key)(&master_keyblock,
+ &krb5_csarray[etype]->random_sequence)) {
+ com_err(argv[0], retval,
+ "while setting up random key generator for etype %d--etype disabled",
+ etype);
+ krb5_csarray[etype] = 0;
+ }
+ }
+ }
+
+ return(0);
+}
+
+krb5_error_code
+init_db(context, dbname, masterkeyname, masterkeyblock)
+ krb5_context context;
+ char *dbname;
+ krb5_principal masterkeyname;
+ krb5_keyblock *masterkeyblock;
+{
+ krb5_error_code retval;
+
+ krb5_db_entry server_entry;
+ krb5_boolean more;
+ int number_of_entries;
+ char tgs_name[255];
+
+ /* set db name if appropriate */
+ if (dbname && (retval = krb5_db_set_name(context, dbname)))
+ return(retval);
+
+ /* initialize database */
+ if (retval = krb5_db_init(context))
+ return(retval);
+
+ if (retval = krb5_db_verify_master_key(context, masterkeyname,
+ masterkeyblock,
+ &master_encblock)) {
+ master_encblock.crypto_entry = 0;
+ return(retval);
+ }
+
+ /* do any necessary key pre-processing */
+ if (retval = krb5_process_key(context, &master_encblock, masterkeyblock)) {
+ master_encblock.crypto_entry = 0;
+ (void) krb5_db_fini(context);
+ return(retval);
+ }
+
+/*
+ * fetch the master database entry, and hold on to it.
+ */
+ number_of_entries = 1;
+ if (retval = krb5_db_get_principal(context, masterkeyname, &master_entry,
+ &number_of_entries, &more)) {
+ return(retval);
+ }
+ if (number_of_entries != 1) {
+ if (number_of_entries)
+ krb5_db_free_principal(context, &master_entry, number_of_entries);
+ return(KRB5_KDB_NOMASTERKEY);
+ } else if (more) {
+ krb5_db_free_principal(context, &master_entry, number_of_entries);
+ return(KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE);
+ }
+
+/*
+ fetch the TGS key, and hold onto it; this is an efficiency hack
+ the master key name here is from the master_princ global,
+ so we can safely share its substructure
+ */
+ strcpy(tgs_name, KRB5_TGS_NAME);
+ strcat(tgs_name, "/");
+ strcat(tgs_name, masterkeyname->realm.data);
+ strcat(tgs_name, "@");
+ strcat(tgs_name, masterkeyname->realm.data);
+ krb5_parse_name(context, tgs_name, &tgs_server);
+
+ tgs_server->type = KRB5_NT_SRV_INST;
+
+ number_of_entries = 1;
+ if (retval = krb5_db_get_principal(context,
+ tgs_server,
+ &server_entry,
+ &number_of_entries,
+ &more)) {
+ return(retval);
+ }
+
+ if (more) {
+ krb5_db_free_principal(context, &server_entry, number_of_entries);
+ (void) krb5_finish_key(context, &master_encblock);
+ memset((char *)&master_encblock, 0, sizeof(master_encblock));
+ (void) krb5_db_fini(context);
+ return(KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE);
+ } else if (number_of_entries != 1) {
+ krb5_db_free_principal(context, &server_entry, number_of_entries);
+ (void) krb5_finish_key(context, &master_encblock);
+ memset((char *)&master_encblock, 0, sizeof(master_encblock));
+ (void) krb5_db_fini(context);
+ return(KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN);
+ }
+
+/*
+ convert server.key into a real key
+ (it may be encrypted in the database)
+ */
+ if (retval = KDB_CONVERT_KEY_OUTOF_DB(context,&server_entry.key,&tgs_key)) {
+ krb5_db_free_principal(context, &server_entry, number_of_entries);
+ (void) krb5_finish_key(context, &master_encblock);
+ memset((char *)&master_encblock, 0, sizeof(master_encblock));
+ (void) krb5_db_fini(context);
+ return(retval);
+ }
+
+ tgs_kvno = server_entry.kvno;
+ krb5_db_free_principal(context, &server_entry, number_of_entries);
+ return(0);
+}
+
+krb5_sigtype
+request_exit()
+{
+ signal_requests_exit = 1;
+ return;
+}
+
+void
+setup_signal_handlers()
+{
+ krb5_sigtype request_exit();
+
+ (void)signal(SIGINT, request_exit);
+ (void)signal(SIGHUP, request_exit);
+ (void)signal(SIGTERM, request_exit);
+ return;
+}
+
+static void
+kdc_com_err_proc(whoami, code, format, pvar)
+ const char *whoami;
+ long code;
+ const char *format;
+ va_list pvar;
+{
+#ifndef __STDC__
+ extern int vfprintf();
+#endif
+
+ if (whoami) {
+ fputs(whoami, stderr);
+ fputs(": ", stderr);
+ }
+
+ if (code) {
+ fputs(error_message(code), stderr);
+ fputs(" ", stderr);
+ }
+
+ if (format) {
+ vfprintf (stderr, format, pvar);
+ }
+
+ putc('\n', stderr);
+ /* should do this only on a tty in raw mode */
+ putc('\r', stderr);
+ fflush(stderr);
+
+ if (format) {
+ /* now need to frob the format a bit... */
+ if (code) {
+ char *nfmt;
+ nfmt = (char *) malloc(
+ strlen(format)+strlen(error_message(code))+2);
+ strcpy(nfmt, error_message(code));
+ strcat(nfmt, " ");
+ strcat(nfmt, format);
+ vsyslog(LOG_ERR, nfmt, pvar);
+ } else {
+ vsyslog(LOG_ERR, format, pvar);
+ }
+ } else {
+ if (code) {
+ syslog(LOG_ERR, "%s", error_message(code));
+ }
+ }
+ return;
+}
+
+void
+setup_com_err(context)
+ krb5_context context;
+{
+ krb5_init_ets(context);
+
+ (void) set_com_err_hook(kdc_com_err_proc);
+ return;
+}
+
+/*
+** Main does the logical thing, it sets up the database and RPC interface,
+** as well as handling the creation and maintenance of the syslog file...
+*/
+main(argc, argv) /* adm_server main routine */
+int argc;
+char **argv;
+{
+ krb5_context context;
+ krb5_error_code retval;
+ int errout = 0;
+
+ adm5_ver_len = ADM5_VERSIZE;
+
+ /* Get the Name of this program (adm_server) for Error Messages */
+ if (strrchr(argv[0], '/'))
+ argv[0] = (char *)strrchr(argv[0], '/') + 1;
+
+ krb5_init_context(&context);
+ setup_com_err(context);
+
+ /* Use Syslog for Messages */
+#ifndef LOG_AUTH /* 4.2 syslog */
+#define LOG_AUTH 0
+ openlog(argv[0], LOG_CONS|LOG_NDELAY|LOG_PID, LOG_LOCAL6);
+#else
+ openlog(argv[0], LOG_AUTH|LOG_CONS|LOG_NDELAY|LOG_PID, LOG_LOCAL6);
+#endif /* LOG_AUTH */
+
+ process_args(context, argc, argv); /* includes reading master key */
+
+ setup_signal_handlers();
+
+ if (retval = init_db(context, dbm_db_name, master_princ,&master_keyblock)) {
+ com_err(argv[0], retval, "while initializing database");
+ exit(1);
+ }
+
+ if (retval = setup_network(context, argv[0])) {
+ exit(1);
+ }
+
+ syslog(LOG_AUTH | LOG_INFO, "Admin Server Commencing Operation");
+
+ if (retval = adm5_listen_and_process(context, argv[0])){
+ krb5_free_principal(context, client_server_info.server);
+ com_err(argv[0], retval, "while processing network requests");
+ errout++;
+ }
+
+ free(client_server_info.name_of_service);
+ krb5_free_principal(context, client_server_info.server);
+
+ if (errout = closedown_network(argv[0])) {
+ com_err(argv[0], retval, "while shutting down network");
+ retval = retval + errout;
+ }
+
+ if (errout = closedown_db(context)) {
+ com_err(argv[0], retval, "while closing database");
+ retval = retval + errout;
+ }
+
+ syslog(LOG_AUTH | LOG_INFO, "Admin Server Shutting Down");
+
+ printf("Admin Server (kadmind) has completed operation.\n");
+
+ exit(retval);
+}
--- /dev/null
+
+/*
+ * Sandia National Laboratories also makes no representations about the
+ * suitability of the modifications, or additions to this software for
+ * any purpose. It is provided "as is" without express or implied warranty.
+ */
+
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <syslog.h>
+#include <stdio.h>
+
+#define MAX_KTXT_LEN 1250
+#define ANAME_SZ 40
+#define INST_SZ 40
+#define REALM_SZ 40
+#define DATE_SZ 26
+
+typedef unsigned char des_cblock[8]; /* crypto-block size */
+#define C_Block des_cblock
+typedef struct des_ks_struct { des_cblock _; } des_key_schedule[16];
+#define Key_schedule des_key_schedule
+
+int des_debug = 0;
+
+struct ktext {
+ int length; /* Length of the text */
+ unsigned char dat[MAX_KTXT_LEN]; /* The data itself */
+ unsigned long mbz; /* zero to catch runaway strings */
+};
+
+typedef struct ktext *KTEXT;
+typedef struct ktext KTEXT_ST;
+
+struct auth_dat {
+ unsigned char k_flags; /* Flags from ticket */
+ char pname[ANAME_SZ]; /* Principal's name */
+ char pinst[INST_SZ]; /* His Instance */
+ char prealm[REALM_SZ]; /* His Realm */
+ unsigned long checksum; /* Data checksum (opt) */
+ C_Block session; /* Session Key */
+ int life; /* Life of ticket */
+ unsigned long time_sec; /* Time ticket issued */
+ unsigned long address; /* Address in ticket */
+ KTEXT_ST reply; /* Auth reply (opt) */
+};
+
+typedef struct auth_dat AUTH_DAT;
+
+#define KADM_VERSTR "SKADM.m1"
+#define KADM_VERSIZE strlen(KADM_VERSTR)
+
+struct msg_dat {
+ unsigned char *app_data; /* pointer to appl data */
+ unsigned long app_length; /* length of appl data */
+ unsigned long hash; /* hash to lookup replay */
+ int swap; /* swap bytes? */
+ long time_sec; /* msg timestamp seconds */
+ unsigned char time_5ms; /* msg timestamp 5ms units */
+};
+
+typedef struct msg_dat MSG_DAT;
+
+typedef struct {
+ char name[ANAME_SZ];
+ char instance[INST_SZ];
+
+ unsigned long key_low;
+ unsigned long key_high;
+ unsigned long exp_date;
+ char exp_date_txt[DATE_SZ];
+ unsigned long mod_date;
+ char mod_date_txt[DATE_SZ];
+ unsigned short attributes;
+ unsigned char max_life;
+ unsigned char kdc_key_ver;
+ unsigned char key_version;
+
+ char mod_name[ANAME_SZ];
+ char mod_instance[INST_SZ];
+ char *old;
+} V4_Principal;
+
+ /* V5 Definitions */
+#include "k5-int.h"
+#include "adm_extern.h"
+
+struct saltblock {
+ int salttype;
+ krb5_data saltdata;
+};
+
+struct cpw_keyproc_arg {
+ krb5_keyblock *key;
+};
+
+/*
+process_v4_kpasswd
+unwrap the data stored in dat, process, and return it.
+ */
+process_v4_kpasswd(dat, dat_len, cpw_key)
+u_char **dat;
+int *dat_len;
+struct cpw_keyproc_arg *cpw_key;
+
+{
+ u_char *in_st; /* pointer into the sent packet */
+ int in_len,retc; /* where in packet we are, for
+ returns */
+ u_long r_len; /* length of the actual packet */
+ KTEXT_ST authent; /* the authenticator */
+ AUTH_DAT ad; /* who is this, klink */
+ u_long ncksum; /* checksum of encrypted data */
+ des_key_schedule sess_sched; /* our schedule */
+ MSG_DAT msg_st;
+ u_char *retdat, *tmpdat;
+ int retval, retlen;
+ u_short dlen;
+ extern int errno;
+
+ if (strncmp(KADM_VERSTR, (char *) *dat, KADM_VERSIZE)) {
+ syslog(LOG_ERR, "process_v4_kpasswd: Bad Version String");
+ return(1);
+ }
+
+ in_len = KADM_VERSIZE;
+ /* get the length */
+ if ((retc = stv_long(*dat, &r_len, in_len, *dat_len)) < 0) {
+ syslog(LOG_AUTH | LOG_INFO, "process_v4_kpasswd: Bad Length");
+ return(1);
+ }
+
+ in_len += retc;
+ authent.length = *dat_len - r_len - KADM_VERSIZE - sizeof(u_long);
+ memcpy((char *) authent.dat, (char *) (*dat) + in_len, authent.length);
+ authent.mbz = 0;
+
+ if (retval = krb_set_key(cpw_key->key->contents, 0) != 0) {
+ syslog(LOG_ERR, "process_v4_kpasswd: Bad set_key Request");
+ return(1);
+ }
+
+ /* service key should be set before here */
+ if (retc = krb4_rd_req(&authent,
+ CPWNAME,
+ client_server_info.server->realm.data,
+ client_server_info.client_name.sin_addr.s_addr,
+ &ad,
+ (char *) 0)) {
+ syslog(LOG_AUTH | LOG_INFO, "process_v4_kpasswd: Bad Read Request");
+ return(1);
+ }
+
+#define clr_cli_secrets() \
+{ \
+ memset((char *) sess_sched, 0, sizeof(sess_sched)); \
+ memset((char *) ad.session, 0, sizeof(ad.session)); \
+}
+
+ in_st = *dat + *dat_len - r_len;
+ ncksum = des_quad_cksum(in_st, (u_long *) 0, (long) r_len, 0, ad.session);
+ if (ncksum!=ad.checksum) { /* yow, are we correct yet */
+ clr_cli_secrets();
+ syslog(LOG_ERR, "process_v4_kpasswd: Invalid Checksum");
+ return(1);
+ }
+
+ des_key_sched(ad.session, sess_sched);
+
+ if (retc = (int) krb4_rd_priv(in_st,
+ r_len,
+ sess_sched,
+ ad.session,
+ &client_server_info.client_name,
+ &client_server_info.server_name,
+ &msg_st)) {
+ syslog(LOG_ERR, "process_v4_kpasswd: Bad Read Private Code = %d",
+ retc);
+ clr_cli_secrets();
+ return(1);
+ }
+
+ if (msg_st.app_data[0] != 2) { /* Only Valid Request is CHANGE_PW = 2 */
+ syslog(LOG_ERR, "process_v4_kpasswd: Invalid V4 Request");
+ clr_cli_secrets();
+ return(1);
+ }
+
+ retval = adm_v4_cpw(msg_st.app_data+1,
+ (int) msg_st.app_length,
+ &ad,
+ &retdat,
+ &retlen);
+
+ if (retval) {
+ syslog(LOG_ERR,
+ "process_v4_kpasswd: Password Modification for %s%s%s Failed",
+ ad.pname, (ad.pinst[0] != '\0') ? "/" : "",
+ (ad.pinst[0] != '\0') ? ad.pinst : "");
+ } else {
+ syslog(LOG_ERR,
+ "process_v4_kpasswd: Password Modification for %s%s%s Complete",
+ ad.pname, (ad.pinst[0] != '\0') ? "/" : "",
+ (ad.pinst[0] != '\0') ? ad.pinst : "");
+ }
+
+ /* Now seal the response back into a priv msg */
+ free((char *)*dat);
+ tmpdat = (u_char *) malloc((unsigned)(retlen + KADM_VERSIZE +
+ sizeof(u_long)));
+
+ (void) strncpy((char *) tmpdat, KADM_VERSTR, KADM_VERSIZE);
+
+ retval = htonl((u_long) retval);
+
+ memcpy((char *) tmpdat + KADM_VERSIZE, (char *) &retval, sizeof(u_long));
+
+ if (retlen) {
+ memcpy((char *) tmpdat + KADM_VERSIZE + sizeof(u_long),
+ (char *) retdat, retlen);
+ free((char *) retdat);
+ }
+
+ /* slop for mk_priv stuff */
+ *dat = (u_char *) malloc((unsigned) (retlen + KADM_VERSIZE +
+ sizeof(u_long) + 200));
+
+ if ((*dat_len = krb4_mk_priv(tmpdat, *dat,
+ (u_long) (retlen + KADM_VERSIZE +
+ sizeof(u_long)),
+ sess_sched,
+ ad.session,
+ &client_server_info.server_name,
+ &client_server_info.client_name)) < 0) {
+ clr_cli_secrets();
+ syslog(LOG_ERR, "process_v4_kpasswd: Bad mk_priv");
+ return(1);
+ }
+
+ dlen = (u_short) *dat_len;
+
+ dlen = htons(dlen);
+
+ if (krb5_net_write(context, client_server_info.client_socket,
+ (char *) &dlen, 2) < 0) {
+ syslog(LOG_ERR, "process_v4_kpasswd: Error writing dlen to client");
+ (void) close(client_server_info.client_socket);
+ }
+
+ if (krb5_net_write(context, client_server_info.client_socket,
+ (char *) *dat, *dat_len) < 0) {
+ syslog(LOG_ERR, "writing to client: %s",error_message(errno));
+ (void) close(client_server_info.client_socket);
+ }
+
+ free((char *) *dat);
+ clr_cli_secrets();
+
+ return(0);
+}
+
+krb5_kvno
+princ_exists(context, principal, entry)
+ krb5_context context;
+ krb5_principal principal;
+ krb5_db_entry *entry;
+{
+ int nprincs = 1;
+ krb5_boolean more;
+ krb5_error_code retval;
+ krb5_kvno vno;
+
+ nprincs = 1;
+ if (retval = krb5_db_get_principal(context, principal, entry,
+ &nprincs, &more)) {
+ return 0;
+ }
+
+ if (!nprincs)
+ return 0;
+
+ return(nprincs);
+}
+
+/*
+adm_v4_cpw - the server side of the change_password routine
+ recieves : KTEXT, {key}
+ returns : CKSUM, RETCODE
+ acl : caller can change only own password
+
+Replaces the password (i.e. des key) of the caller with that specified in key.
+Returns no actual data from the master server, since this is called by a user
+*/
+int
+adm_v4_cpw(dat, len, ad, datout, outlen)
+u_char *dat;
+int len;
+AUTH_DAT *ad;
+u_char **datout;
+int *outlen;
+{
+ krb5_db_entry entry;
+ krb5_keyblock *v5_keyblock;
+
+ int number_of_principals;
+ krb5_error_code retval;
+ int one = 1;
+ char v5_principal[255];
+
+ C_Block v4_clear_key;
+ unsigned long keylow, keyhigh;
+ int stvlen;
+
+ /* Identify the Customer */
+ (void) sprintf(v5_principal, "%s%s%s\0", ad->pname,
+ (ad->pinst[0] != '\0') ? "/" : "",
+ (ad->pinst[0] != '\0') ? ad->pinst : "");
+
+ /* take key off the stream, and change the database */
+
+ if ((stvlen = stv_long(dat, &keyhigh, 0, len)) < 0) {
+ syslog(LOG_ERR, "adm_v4_cpw - (keyhigh) Length Error for stv_long");
+ return(1);
+ }
+ if (stv_long(dat, &keylow, stvlen, len) < 0) {
+ syslog(LOG_ERR, "adm_v4_cpw - (keylow) Length Error for stv_long");
+ return(1);
+ }
+
+ keylow = ntohl(keylow);
+ keyhigh = ntohl(keyhigh);
+
+ /* Convert V4 Key to V5 Key */
+ (void) memcpy(v4_clear_key, (char *) &keylow, 4);
+ (void) memcpy(((long *) v4_clear_key) + 1, (char *) &keyhigh, 4);
+
+ /* Zero Next Output Entry */
+ memset((char *) &entry, 0, sizeof(entry));
+
+ if (retval = krb5_parse_name(context, v5_principal, &entry.principal)) {
+ syslog(LOG_ERR, "adm_v4_cpw - Error parsing %s",
+ v5_principal);
+ return(1);
+ }
+
+ if (!(number_of_principals = princ_exists(entry.principal, &entry))) {
+ syslog(LOG_ERR, "adm_v4_cpw - principal %s is NOT in the database",
+ v5_principal);
+ return(1);
+ }
+
+ /* Allocate v5_keyblock and fill some fields */
+ if (!(v5_keyblock = (krb5_keyblock *) calloc (1,
+ sizeof(krb5_keyblock)))) {
+ syslog(LOG_ERR, "adm_v4_cpw - Error Allocating krb5_keyblock");
+ return(1);
+ }
+
+ v5_keyblock->keytype = KEYTYPE_DES;
+ v5_keyblock->length = 8;
+ if (!(v5_keyblock->contents = (krb5_octet *) calloc (1,
+ 8))) {
+ syslog(LOG_ERR,
+ "adm_v4_cpw - Error Allocating krb5_keyblock->contents\n");
+ free(v5_keyblock);
+ return(1);
+ }
+
+ memcpy(v5_keyblock->contents, v4_clear_key, 8);
+
+ if (retval = krb5_kdb_encrypt_key(context, &master_encblock,
+ v5_keyblock,
+ &entry.key)) {
+ syslog(LOG_ERR,
+ "adm_v4_cpw - Error %d while encrypting key for '%s'\n", retval,
+ v5_principal);
+ return(1);
+ }
+ entry.alt_key.length = 0;
+
+ /* Increment Version Number */
+ entry.kvno = entry.kvno + 1;
+#ifdef SANDIA
+ entry.attributes &= ~KRB5_KDB_REQUIRES_PWCHANGE;
+#endif
+ if (retval = krb5_timeofday(context, &entry.mod_date)) {
+ syslog(LOG_ERR, "adm_v4_cpw - Error while fetching date");
+ return(1);
+ }
+#ifdef SANDIA
+ entry.last_pwd_change = entry.mod_date;
+#endif
+ entry.mod_name = entry.principal; /* Should be Person who did Action */
+
+ /* Write the Modified Principal to the V5 Database */
+ if (retval = krb5_db_put_principal(context, &entry, &one)) {
+ syslog(LOG_ERR,
+ "adm_v4_cpw - Error %d while Entering Principal for '%s'",
+ retval, v5_principal);
+ return(1);
+ }
+
+ *datout = 0;
+ *outlen = 0;
+
+ return(0);
+}
+
+stv_long(st, dat, loc, maxlen)
+u_char *st; /* a base pointer to the stream */
+u_long *dat; /* the attributes field */
+int loc; /* offset into the stream for current data */
+int maxlen; /* maximum length of st */
+{
+ u_long temp = 0; /* to hold the net order short */
+
+#if (SIZEOF_LONG == 4)
+ if (loc + 4 > maxlen)
+ return(-1);
+ (void) memcpy((char *) &temp + 4, (char *) ((u_long)st + (u_long)loc), 4);
+ *dat = ntohl(temp); /* convert to network order */
+ return(4);
+#else
+ if (loc + sizeof(u_long) > maxlen)
+ return(-1);
+ (void) memcpy((char *) &temp, (char *) ((u_long)st + (u_long)loc),
+ sizeof(u_long));
+ *dat = ntohl(temp); /* convert to network order */
+ return(sizeof(u_long));
+#endif
+}
--- /dev/null
+# Administrator Access Control List
+# Format:
+# Name Privileges Comments
+# Where Privileges is a string containing one or more of
+# "a" Add New Principals
+# "c" Change Passwords
+# "d" Delete Current Principals
+# "i" Inquire About Existing Principals
+# "m" Modify Existing Principals
+# "*" All Privileges
+#jqsample/admin@realm *
+#tomjones/admin@realm acim # Note - May Not Delete
--- /dev/null
+AC_INIT(adm_kadmin.c)
+WITH_CCOPTS
+CONFIG_RULES
+AC_SET_BUILDTOP
+AC_PROG_INSTALL
+WITH_NETLIB
+AC_CHECK_LIB(ndbm,main)
+AC_CHECK_LIB(dbm,main)
+AC_TIME_WITH_SYS_TIME
+ET_RULES
+KRB_INCLUDE
+WITH_KRB5ROOT
+CHECK_SIGPROCMASK
+V5_AC_OUTPUT_MAKEFILE
--- /dev/null
+.\" this should not be empty