summaryrefslogtreecommitdiffstats
path: root/src/kadmin/kpasswd
diff options
context:
space:
mode:
authorTheodore Tso <tytso@mit.edu>1992-09-29 14:51:34 +0000
committerTheodore Tso <tytso@mit.edu>1992-09-29 14:51:34 +0000
commitd4e95b17ce5d033759cb529f0cada608982ef5c8 (patch)
tree0182c5c657e0df883466a0aa593788829919b39b /src/kadmin/kpasswd
parentd96ae575ff8eef11fe1dfb3bffdede9d31cb5e57 (diff)
downloadkrb5-d4e95b17ce5d033759cb529f0cada608982ef5c8.tar.gz
krb5-d4e95b17ce5d033759cb529f0cada608982ef5c8.tar.xz
krb5-d4e95b17ce5d033759cb529f0cada608982ef5c8.zip
*** empty log message ***
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@2444 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src/kadmin/kpasswd')
-rw-r--r--src/kadmin/kpasswd/Imakefile40
-rw-r--r--src/kadmin/kpasswd/kpasswd.M0
-rw-r--r--src/kadmin/kpasswd/kpasswd.c998
-rw-r--r--src/kadmin/kpasswd/networked.c226
4 files changed, 1264 insertions, 0 deletions
diff --git a/src/kadmin/kpasswd/Imakefile b/src/kadmin/kpasswd/Imakefile
new file mode 100644
index 000000000..11329ca1c
--- /dev/null
+++ b/src/kadmin/kpasswd/Imakefile
@@ -0,0 +1,40 @@
+# $Source$
+# $Author$
+# $Header$
+#
+# Copyright 1989 by the Massachusetts Institute of Technology.
+#
+# For copying and distribution information,
+# please see the file <mit-copyright.h>.
+#
+# Imakefile for Kerberos admin server library.
+
+#ifdef Krb4KDCCompat
+K4LIB=-l$(DES425LIB)
+#else
+K4LIB=
+#endif
+
+SRCS = \
+ networked.c \
+ kpasswd.c
+
+OBJS = \
+ networked.o \
+ kpasswd.o
+
+ErrorTableObjectRule()
+
+all:: kpasswd
+
+NormalProgramTarget(kpasswd,$(OBJS),$(KDBDEPLIB) $(DEPKLIB), \
+ $(KDBLIB) $(K4LIB) $(KLIB) ,)
+Krb5InstallClientProgram(kpasswd)
+
+clean::
+
+depend::
+
+clean::
+
+DependTarget()
diff --git a/src/kadmin/kpasswd/kpasswd.M b/src/kadmin/kpasswd/kpasswd.M
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/kadmin/kpasswd/kpasswd.M
diff --git a/src/kadmin/kpasswd/kpasswd.c b/src/kadmin/kpasswd/kpasswd.c
new file mode 100644
index 000000000..c4a070ede
--- /dev/null
+++ b/src/kadmin/kpasswd/kpasswd.c
@@ -0,0 +1,998 @@
+/*
+ * $Source$
+ * $Author$
+ *
+ * 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.
+ */
+
+#ifndef lint
+static char rcsid_kpasswd_c[] =
+ "$Header$";
+#endif /* lint */
+
+/*
+ * 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>
+#ifndef __convex__
+#include <strings.h>
+#endif
+
+#ifndef MAXPATHLEN
+#define MAXPATHLEN 1024
+#endif
+
+#include <sys/param.h>
+#include <pwd.h>
+
+#include <krb5/adm_defs.h>
+
+#include <sys/stat.h>
+
+#include <krb5/krb5.h>
+#include <krb5/kdb.h>
+#include <krb5/kdb_dbm.h>
+#include <krb5/ext-proto.h>
+#include <krb5/los-proto.h>
+#include <krb5/asn1.h>
+#include <krb5/config.h>
+#include <krb5/base-defs.h>
+#include <krb5/asn.1/encode.h>
+
+#include <krb5/widen.h>
+
+#include <krb5/adm_err.h>
+#include <krb5/errors.h>
+#include <krb5/kdb5_err.h>
+#include <krb5/krb5_err.h>
+
+krb5_error_code get_first_ticket
+ PROTOTYPE((krb5_ccache,
+ krb5_principal));
+
+krb5_error_code print_and_choose_password
+ PROTOTYPE((char *, krb5_data *));
+
+struct sockaddr_in local_sin, remote_sin;
+
+krb5_creds my_creds;
+
+struct v4_pwd_keyproc_arg {
+ krb5_principal who;
+ krb5_data password;
+};
+
+extern char *krb5_default_pwd_prompt1;
+
+static krb5_error_code
+v4_pwd_keyproc(DECLARG(const krb5_keytype, type),
+ DECLARG(krb5_keyblock **, key),
+ DECLARG(krb5_const_pointer, keyseed),
+ DECLARG(krb5_pa_data **,padata))
+OLDDECLARG(const krb5_keytype, type)
+OLDDECLARG(krb5_keyblock **, key)
+OLDDECLARG(krb5_const_pointer, keyseed)
+OLDDECLARG(krb5_pa_data **, padata)
+{
+ krb5_data salt;
+ krb5_error_code retval;
+#ifdef unicos61
+ struct v4_pwd_keyproc_arg *arg;
+#else
+ const struct v4_pwd_keyproc_arg *arg;
+#endif /* unicos61 */
+ struct v4_pwd_keyproc_arg arg2;
+ char pwdbuf[BUFSIZ];
+ int pwsize = sizeof(pwdbuf);
+ char f_salt = 0, use_salt = 0;
+ krb5_keyblock *my_keyblock;
+ char v4_keyptr[8];
+
+ if (!valid_keytype(type))
+ return KRB5_PROG_KEYTYPE_NOSUPP;
+
+ if (padata) {
+ krb5_pa_data **ptr;
+
+ for (ptr = padata; *ptr; ptr++)
+ {
+ if ((*ptr)->pa_type == KRB5_PADATA_PW_SALT)
+ {
+ /* use KDC-supplied salt, instead of default */
+ salt.length = (*ptr)->length;
+ salt.data = (char *)(*ptr)->contents;
+ use_salt = 1;
+ break;
+ }
+ }
+ }
+#ifdef unicos61
+ arg = (struct v4_pwd_keyproc_arg *) keyseed;
+#else
+ arg = (const struct v4_pwd_keyproc_arg *) keyseed;
+#endif /* unicos61 */
+ if (!use_salt) {
+ /* need to use flattened principal */
+ if (retval = krb5_principal2salt(arg->who, &salt))
+ return(retval);
+ f_salt = 1;
+ }
+
+ if (!arg->password.length) {
+ if (retval = krb5_read_password(krb5_default_pwd_prompt1,
+ 0,
+ pwdbuf, &pwsize)) {
+ if (f_salt) xfree(salt.data);
+ return retval;
+ }
+
+ arg2 = *arg;
+ arg2.password.length = pwsize;
+ arg2.password.data = pwdbuf;
+ arg = &arg2;
+ }
+ my_keyblock = (krb5_keyblock *)malloc(sizeof(**key));
+ if (!*key) {
+ if (f_salt) xfree(salt.data);
+ if (arg != (struct v4_pwd_keyproc_arg *) keyseed)
+ memset((char *) arg->password.data, 0, arg->password.length);
+ return(ENOMEM);
+ }
+
+ *key = my_keyblock;
+ (*my_keyblock).keytype = type;
+ (*my_keyblock).length = 8;
+
+ if (retval = des_string_to_key(arg->password.data,
+ v4_keyptr)) {
+ xfree(*key);
+ if (f_salt) xfree(salt.data);
+ if (arg != (struct v4_pwd_keyproc_arg *) keyseed)
+ memset((char *)arg->password.data,0,arg->password.length);
+ return(retval);
+ }
+
+ (*my_keyblock).contents = (krb5_octet *)calloc(1,(*my_keyblock).length);
+ if (!(*my_keyblock).contents) return(ENOMEM);
+ memcpy((*my_keyblock).contents,(krb5_octet *) v4_keyptr,
+ (*my_keyblock).length);
+
+ if (f_salt) xfree(salt.data);
+ if (arg != (struct v4_pwd_keyproc_arg *) keyseed)
+ memset((char *)arg->password.data,0,arg->password.length);
+ return(0);
+}
+
+main(argc,argv)
+ int argc;
+ char *argv[];
+{
+ krb5_ccache cache = NULL;
+ char cache_name[255];
+ krb5_flags cc_flags;
+
+ krb5_address local_addr, foreign_addr;
+
+ struct passwd *pw;
+
+ krb5_principal client;
+ krb5_principal server;
+
+ char default_name[256];
+ char *client_name; /* Single string representation of client id */
+
+ krb5_data requested_realm;
+ char * local_realm;
+
+ char input_string[768];
+
+ krb5_error_code retval; /* return code */
+
+ int local_socket;
+ int c, count;
+
+ krb5_error *err_ret;
+ krb5_ap_rep_enc_part *rep_ret;
+
+ kadmin_requests rd_priv_resp;
+
+ krb5_checksum send_cksum;
+ int cksum_alloc = 0;
+ krb5_data msg_data, inbuf;
+ krb5_int32 seqno;
+
+ char *new_password;
+ int new_pwsize;
+ krb5_data *decodable_pwd_string;
+ int i, j;
+
+#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_ets();
+ memset((char *) default_name, 0, sizeof(default_name));
+
+ switch (argc) {
+ case 1: /* No User Specified */
+
+ /* Identify Default Credentials Cache */
+ if ((retval = krb5_cc_default(&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(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(default_name, &client))) {
+ fprintf(stderr, "Unable to Parse Client Name!\n");
+ goto finish;
+ }
+
+ if ((retval = krb5_unparse_name(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(cache,
+ (krb5_principal *) &client))) {
+ fprintf(stderr,
+ "Unable to Read Customer Credentials File!\n");
+ goto finish;
+ }
+
+ if ((retval = krb5_unparse_name(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(cache);
+ }
+ break;
+
+ case 2: /* Client Gave us a Token - Use it */
+ /* Hand Parse Entry */
+ strcpy(input_string, argv[1]);
+
+ if (retval = krb5_parse_name(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(cache_name, &cache))) {
+ fprintf(stderr, "Unable to Resolve Cache: %s\n", cache_name);
+ }
+
+ if ((retval = krb5_cc_initialize(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(cache, client))) {
+ goto finish;
+ }
+
+ /* Initiate Link to Server */
+ if ((retval = adm5_init_link(&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(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;
+
+ /* compute checksum, using CRC-32 */
+ if (!(send_cksum.contents = (krb5_octet *)
+ malloc(krb5_checksum_size(CKSUMTYPE_CRC32)))) {
+ fprintf(stderr, "Insufficient Memory while Allocating Checksum!\n");
+ goto finish;
+ }
+ cksum_alloc++;
+ /* choose some random stuff to compute checksum from */
+ if (retval = krb5_calculate_checksum(CKSUMTYPE_CRC32,
+ ADM_CPW_VERSION,
+ strlen(ADM_CPW_VERSION),
+ 0,
+ 0, /* if length is 0, crc-32 doesn't
+ use the seed */
+ &send_cksum)) {
+ fprintf(stderr, "Error while Computing Checksum: %s!\n",
+ error_message(retval));
+ goto finish;
+ }
+
+ /* call Kerberos library routine to obtain an authenticator,
+ pass it over the socket to the server, and obtain mutual
+ authentication. */
+
+ if ((retval = krb5_sendauth((krb5_pointer) &local_socket,
+ ADM_CPW_VERSION,
+ my_creds.client,
+ my_creds.server,
+ AP_OPTS_MUTUAL_REQUIRED,
+ &send_cksum,
+ 0,
+ cache,
+ &seqno,
+ 0, /* don't need a subsession key */
+ &err_ret,
+ &rep_ret))) {
+ fprintf(stderr, "Error while performing sendauth: %s!\n",
+ error_message(retval));
+ goto finish;
+ }
+
+ /* Get credentials : to use for safe and private messages */
+ if (retval = krb5_get_credentials(0, cache, &my_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(&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.data[0] = KPASSWD;
+ inbuf.data[1] = CHGOPER;
+ inbuf.length = 2;
+
+ if ((retval = krb5_mk_priv(&inbuf,
+ ETYPE_DES_CBC_CRC,
+ &my_creds.keyblock,
+ &local_addr,
+ &foreign_addr,
+ seqno,
+ KRB5_PRIV_DOSEQUENCE|KRB5_PRIV_NOTIME,
+ 0,
+ 0,
+ &msg_data))) {
+ 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(&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(&local_socket, &inbuf)){
+ fprintf(stderr, "Read Error During First Reply: %s!\n",
+ error_message(retval));
+ retval = 1;
+ goto finish;
+ }
+
+ if ((retval = krb5_rd_priv(&inbuf,
+ &my_creds.keyblock,
+ &foreign_addr,
+ &local_addr,
+ rep_ret->seq_number,
+ KRB5_PRIV_DOSEQUENCE|KRB5_PRIV_NOTIME,
+ 0,
+ 0,
+ &msg_data))) {
+ 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(
+ "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;
+ }
+#endif
+
+ inbuf.data = new_password;
+ inbuf.length = strlen(new_password);
+
+ if ((retval = krb5_mk_priv(&inbuf,
+ ETYPE_DES_CBC_CRC,
+ &my_creds.keyblock,
+ &local_addr,
+ &foreign_addr,
+ seqno,
+ KRB5_PRIV_DOSEQUENCE|KRB5_PRIV_NOTIME,
+ 0,
+ 0,
+ &msg_data))) {
+ 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(&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(&local_socket, &inbuf)){
+ fprintf(stderr, "Read Error During Second Reply: %s!\n",
+ error_message(retval));
+ retval = 1;
+ goto finish;
+ }
+
+ if ((retval = krb5_rd_priv(&inbuf,
+ &my_creds.keyblock,
+ &foreign_addr,
+ &local_addr,
+ rep_ret->seq_number,
+ KRB5_PRIV_DOSEQUENCE|KRB5_PRIV_NOTIME,
+ 0,
+ 0,
+ &msg_data))) {
+ fprintf(stderr, "Error during Second Read Decoding :%s!\n",
+ error_message(retval));
+ goto finish;
+ }
+
+ memcpy(&rd_priv_resp.appl_code, msg_data.data, 1);
+ memcpy(&rd_priv_resp.oper_code, msg_data.data + 1, 1);
+ memcpy(&rd_priv_resp.retn_code, msg_data.data + 2, 1);
+
+ free(inbuf.data);
+ free(msg_data.data);
+ if (!((rd_priv_resp.appl_code == KPASSWD) &&
+ (rd_priv_resp.oper_code == CHGOPER) &&
+ (rd_priv_resp.retn_code == KADMGOOD))) {
+ fprintf(stderr, "Generic Error During kpasswd!\n");
+ retval = 1;
+ }
+
+ finish:
+
+ (void) krb5_cc_destroy(cache);
+
+ free(client_name);
+ free(requested_realm.data);
+
+ if (cksum_alloc) free(send_cksum.contents);
+ if (retval) {
+ fprintf(stderr, "\n\nProtocol Failure - %s\n\n",
+ kadmind_kpasswd_response[1]);
+ exit(1);
+ }
+
+ printf("\n\n%s.\n\n", kadmind_kpasswd_response[0]);
+
+ exit(0);
+}
+
+
+
+krb5_data cpwname = {
+ sizeof(CPWNAME)-1,
+ CPWNAME
+};
+
+krb5_error_code
+get_first_ticket(DECLARG(krb5_ccache, cache),
+ DECLARG(krb5_principal, client))
+OLDDECLARG(krb5_ccache, cache)
+OLDDECLARG(krb5_principal, client)
+{
+ char prompt[255]; /* for the password prompt */
+ char verify_prompt[255]; /* Verification Prompt if Desired */
+ char pword[ADM_MAX_PW_LENGTH+1]; /* storage for the password */
+ int pword_length = sizeof(pword);
+ char *old_password;
+ int old_pwsize;
+
+ krb5_address **my_addresses;
+
+ struct v4_pwd_keyproc_arg keyseed;
+
+ char *client_name;
+ char local_realm[255];
+ krb5_error_code retval;
+
+ if ((retval = krb5_unparse_name(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(my_creds));
+
+ my_creds.client = client;
+
+ if ((retval = krb5_build_principal_ext(&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");
+ 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(
+ prompt,
+ 0,
+ old_password,
+ &old_pwsize))) {
+ fprintf(stderr, "Error while reading password for '%s'",
+ client_name);
+ return(1);
+ }
+
+/* Build Request for Initial Credentials */
+ if ((retval = krb5_get_in_tkt_with_password(
+ 0, /* options */
+ my_addresses,
+ /* do random preauth */
+ KRB5_PADATA_ENC_RANDOM,
+ ETYPE_DES_CBC_CRC, /* etype */
+ KEYTYPE_DES,
+ old_password,
+ cache,
+ &my_creds,
+ 0 ))) {
+ keyseed.password.data = (char *) old_password;
+ if (old_password)
+ keyseed.password.length = strlen(old_password);
+ else
+ keyseed.password.length = 0;
+ keyseed.who = my_creds.client;
+/*
+ if ( retval != KDC_ERR_KEY_EXPIRED ) {
+ fprintf(stderr,"\nUnable to Get Initial Credentials : %s %d\n",
+ error_message(retval),retval);
+ return(retval);
+ }
+*/
+ if ((retval = krb5_get_in_tkt(
+ 0, /* options */
+ my_addresses,
+ KRB5_PADATA_ENC_RANDOM, /* do random preauth */
+ ETYPE_DES_CBC_CRC,
+ KEYTYPE_DES,
+ v4_pwd_keyproc,
+ (krb5_pointer) &keyseed,
+ krb5_kdc_rep_decrypt_proc,
+ 0,
+ &my_creds,
+ cache,
+ 0 ))) {
+ fprintf(stderr, "\nUnable to Get Initial Credentials : %s %d\n",
+ error_message(retval),retval);
+ return(retval);
+ }
+ }
+
+ /* Do NOT Forget to zap password */
+ memset((char *) old_password, 0, old_pwsize);
+ free(old_password);
+ memset((char *) pword, 0, sizeof(pword));
+ return(0);
+}
+
+#ifdef MACH_PASS /* Machine-generated Passwords */
+krb5_error_code
+print_and_choose_password(DECLARG(char *, new_password),
+ DECLARG(krb5_data *, decodable_pwd_string))
+OLDDECLARG(char *, new_password)
+OLDDECLARG(krb5_data *, decodable_pwd_string)
+
+{
+krb5_error_code retval;
+ krb5_pwd_data *pwd_data;
+ passwd_phrase_element **next_passwd_phrase_element;
+ char prompt[255];
+ char *verify_prompt = 0;
+ 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(&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
+
+krb5_error_code
+adm5_init_link( realm_of_server, local_socket)
+krb5_data *realm_of_server;
+int * local_socket;
+
+{
+ struct servent *service_process; /* service we will talk to */
+ struct hostent *local_host; /* us */
+ struct hostent *remote_host; /* host we will talk to */
+ struct sockaddr *sockaddr_list;
+
+ 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 (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);
+}
diff --git a/src/kadmin/kpasswd/networked.c b/src/kadmin/kpasswd/networked.c
new file mode 100644
index 000000000..3ddd0ffa5
--- /dev/null
+++ b/src/kadmin/kpasswd/networked.c
@@ -0,0 +1,226 @@
+/* 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.
+ */
+#ifndef _TYPES_
+#include <sys/types.h>
+#ifndef _TYPES_
+#define _TYPES_
+#endif
+#endif
+#include <utmp.h>
+#include <pwd.h>
+
+#ifndef MAXHOSTNAME
+#define MAXHOSTNAME 64
+#endif
+
+int utfile; /* Global utfile file descriptor for BSD version
+ of setutent, getutline, and endutent */
+
+#if !defined(SYSV) && !defined(UMIPS) /* Setutent, Endutent, and getutline
+ routines for non System V Unix
+ systems */
+#include <fcntl.h>
+
+void setutent()
+{
+ utfile = open("/etc/utmp",O_RDONLY);
+}
+
+struct utmp * 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);
+}
+
+void endutent()
+{
+ close(utfile);
+}
+#endif /* not SYSV */
+
+
+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 */
+#ifdef SYSV
+ utmpent.ut_type = USER_PROCESS;
+#define ut_name ut_user
+#endif
+ setutent();
+ while ( (tmpptr = (struct utmp *) 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) {
+ endutent();
+ return(1);
+ }
+ byte_copy((char *)tmpptr,(char *)&retutent,sizeof(struct utmp));
+ 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);
+}
+
+byte_copy(str1,str2,len)
+char *str1, *str2;
+int len;
+{
+ int i;
+ for (i=0;i < len; i++) *(str2 + i) = *(str1 + i);
+ return;
+}
+
+
+#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