summaryrefslogtreecommitdiffstats
path: root/src/appl
diff options
context:
space:
mode:
authorMarc Horowitz <marc@mit.edu>1998-10-30 02:56:35 +0000
committerMarc Horowitz <marc@mit.edu>1998-10-30 02:56:35 +0000
commit1440ab035ba04550ddbbfbff1ee9b5571e3d95db (patch)
tree9d5e8d2e151a930e044c7d0f7c64053d244577a0 /src/appl
parent61ddbf948ba6ee70c1bc049268c3dfa73bc9983e (diff)
pull up 3des implementation from the marc-3des branch
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@11001 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src/appl')
-rw-r--r--src/appl/bsd/ChangeLog23
-rw-r--r--src/appl/bsd/kcmd.c125
-rw-r--r--src/appl/bsd/krlogin.c175
-rw-r--r--src/appl/bsd/krlogind.c175
-rw-r--r--src/appl/bsd/login.c2306
-rw-r--r--src/appl/gss-sample/ChangeLog12
-rw-r--r--src/appl/gss-sample/gss-client.c35
-rw-r--r--src/appl/gss-sample/gss-server.c22
-rw-r--r--src/appl/gssftp/ftp/ChangeLog7
-rw-r--r--src/appl/gssftp/ftp/ftp.c91
-rw-r--r--src/appl/telnet/libtelnet/ChangeLog7
-rw-r--r--src/appl/telnet/libtelnet/enc_des.c109
-rw-r--r--src/appl/telnet/libtelnet/kerberos.c200
-rw-r--r--src/appl/telnet/telnet/ChangeLog7
-rw-r--r--src/appl/telnet/telnet/commands.c8
15 files changed, 1875 insertions, 1427 deletions
diff --git a/src/appl/bsd/ChangeLog b/src/appl/bsd/ChangeLog
index 6eaa52942..8f7e9a8fc 100644
--- a/src/appl/bsd/ChangeLog
+++ b/src/appl/bsd/ChangeLog
@@ -1,3 +1,17 @@
+1998-10-24 Marc Horowitz <marc@mit.edu>
+
+ * login.c: update to new get_creds API
+
+ * krlogin.c (main, oob, server_message, control), krlogind.c
+ (sendoob, protocol, recvauth): If the enctype is not
+ similar to DES, use an inband signalling protocol instead
+ of MSG_OOB data to indicate status changes.
+
+ * kcmd.c (rcmd_stream_init_krb5, v5_des_read, v5_des_write):
+ update to new crypto API. Add ivec chaining to
+ encryption when the enctype is not similar to DES as part
+ of the new protocol.
+
1998-10-06 Theodore Ts'o <tytso@rsts-11.mit.edu>
* krshd.c (doit): Apply ghudson's patch so that rshd passes the
@@ -8,6 +22,10 @@
the foreign and local ports so that encrypted rcp for the
same machine. [krb5-appl/638]
+Tue Aug 18 16:48:02 1998 Tom Yu <tlyu@mit.edu>
+
+ * krlogin.c: Add <sys/filio.h> for FIONREAD.
+
Sat Aug 15 00:01:15 1998 Geoffrey King <gjking@mit.edu>
* krcp.c (error): Don't call rcmd_stream_write if iamremote is not
@@ -19,6 +37,11 @@ Mon Jul 27 00:06:20 1998 Geoffrey King <gjking@mit.edu>
* krlogin.c (main): Apply ghudson's patch so that rlogin -a
no longer dumps core. [krb5-appl/612]
+Sun Jul 26 23:46:36 1998 Sam Hartman <hartmans@utwig.mesas.com>
+
+ * login.c (main): Allow krb524 conversion for forwarded tickets
+ (try_convert524): Don't check to see if we have tickets here; caller does that and actually gets it right.
+
1998-05-26 Theodore Ts'o <tytso@rsts-11.mit.edu>
* login.c (dolastlog): BSD 4.4 systems don't have lastlog.h, but
diff --git a/src/appl/bsd/kcmd.c b/src/appl/bsd/kcmd.c
index c6f21e02f..f77571917 100644
--- a/src/appl/bsd/kcmd.c
+++ b/src/appl/bsd/kcmd.c
@@ -19,6 +19,32 @@
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ *
+ * 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 FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. FundsXpress makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
/* derived from @(#)rcmd.c 5.17 (Berkeley) 6/27/88 */
#ifdef HAVE_UNISTD_H
@@ -76,6 +102,8 @@ extern Key_schedule v4_schedule;
#define START_PORT 5120 /* arbitrary */
char *default_service = "host";
+#define KCMD_KEYUSAGE 1026
+
/*
* Note that the encrypted rlogin packets take the form of a four-byte
* length followed by encrypted data. On writing the data out, a significant
@@ -89,7 +117,8 @@ static char des_inbuf[2*RCMD_BUFSIZ]; /* needs to be > largest read size */
static char des_outpkt[2*RCMD_BUFSIZ+4]; /* needs to be > largest write size */
static krb5_data desinbuf;
static krb5_data desoutbuf;
-static krb5_encrypt_block eblock; /* eblock for encrypt/decrypt */
+static krb5_data encivec;
+static krb5_keyblock *keyblock; /* key for encrypt/decrypt */
static int (*input)();
static int (*output)();
static char storage[2*RCMD_BUFSIZ]; /* storage for the decryption */
@@ -713,12 +742,14 @@ void rcmd_stream_init_normal()
output = twrite;
}
-void rcmd_stream_init_krb5(keyblock, encrypt_flag, lencheck)
- krb5_keyblock *keyblock;
+void rcmd_stream_init_krb5(in_keyblock, encrypt_flag, lencheck)
+ krb5_keyblock *in_keyblock;
int encrypt_flag;
int lencheck;
{
krb5_error_code status;
+ size_t blocksize;
+ krb5_boolean similar;
if (!encrypt_flag) {
rcmd_stream_init_normal();
@@ -726,15 +757,39 @@ void rcmd_stream_init_krb5(keyblock, encrypt_flag, lencheck)
}
desinbuf.data = des_inbuf;
desoutbuf.data = des_outpkt+4; /* Set up des buffers */
- krb5_use_enctype(bsd_context, &eblock, keyblock->enctype);
- if ( status = krb5_process_key(bsd_context, &eblock, keyblock)) {
- fprintf(stderr, "rcmd: Cannot process session key: %s\n",
- error_message(status));
- exit(1);
- }
+ keyblock = in_keyblock;
+
do_lencheck = lencheck;
input = v5_des_read;
output = v5_des_write;
+
+ if (status = krb5_c_enctype_compare(bsd_context, ENCTYPE_DES_CBC_CRC,
+ keyblock->enctype,
+ &similar)) {
+ /* XXX what do I do? */
+ abort();
+ }
+
+ if (similar) {
+ encivec.length = 0;
+ return;
+ }
+
+ if (status = krb5_c_block_size(bsd_context, keyblock->enctype,
+ &blocksize)) {
+ /* XXX what do I do? */
+ abort();
+ }
+
+ encivec.length = blocksize;
+
+ if ((encivec.data = malloc(encivec.length)) == NULL) {
+ /* XXX what do I do? */
+ abort();
+ }
+
+ /* is there a better way to initialize this? */
+ memset(encivec.data, '\0', blocksize);
}
#ifdef KRB5_KRB4_COMPAT
@@ -787,9 +842,12 @@ static int v5_des_read(fd, buf, len)
int len;
{
int nreturned = 0;
- long net_len,rd_len;
+ size_t net_len,rd_len;
int cc;
unsigned char c;
+ krb5_error_code ret;
+ krb5_data plain;
+ krb5_enc_data cipher;
if (nstored >= len) {
memcpy(buf, store_ptr, len);
@@ -823,7 +881,12 @@ static int v5_des_read(fd, buf, len)
if ((cc = krb5_net_read(bsd_context, fd, &c, 1)) != 1) return 0;
rd_len = (rd_len << 8) | c;
- net_len = krb5_encrypt_size(rd_len,eblock.crypto_entry);
+ if (ret = krb5_c_encrypt_length(bsd_context, keyblock->enctype,
+ rd_len, &net_len)) {
+ errno = ret;
+ return(-1);
+ }
+
if ((net_len <= 0) || (net_len > sizeof(des_inbuf))) {
/* preposterous length, probably out of sync */
errno = EIO;
@@ -834,11 +897,17 @@ static int v5_des_read(fd, buf, len)
errno = EIO;
return(-1);
}
+
+ cipher.enctype = ENCTYPE_UNKNOWN;
+ cipher.ciphertext.length = net_len;
+ cipher.ciphertext.data = desinbuf.data;
+ plain.length = sizeof(storage);
+ plain.data = storage;
+
/* decrypt info */
- if ((krb5_decrypt(bsd_context, desinbuf.data,
- (krb5_pointer) storage,
- net_len,
- &eblock, 0))) {
+ if (krb5_c_decrypt(bsd_context, keyblock, KCMD_KEYUSAGE,
+ encivec.length?&encivec:0,
+ &cipher, &plain)) {
/* probably out of sync */
errno = EIO;
return(-1);
@@ -867,21 +936,24 @@ static int v5_des_write(fd, buf, len)
int len;
{
unsigned char *len_buf = (unsigned char *) des_outpkt;
-
- desoutbuf.length = krb5_encrypt_size(len,eblock.crypto_entry);
- if (desoutbuf.length > sizeof(des_outpkt)-4){
- errno = EIO;
- return(-1);
- }
- if ((krb5_encrypt(bsd_context, (krb5_pointer)buf,
- desoutbuf.data,
- len,
- &eblock,
- 0))){
+ krb5_data plain;
+ krb5_enc_data cipher;
+
+ plain.data = buf;
+ plain.length = len;
+
+ cipher.ciphertext.length = sizeof(des_outpkt)-4;
+ cipher.ciphertext.data = desoutbuf.data;
+
+ if (krb5_c_encrypt(bsd_context, keyblock, KCMD_KEYUSAGE,
+ encivec.length?&encivec:0,
+ &plain, &cipher)) {
errno = EIO;
return(-1);
}
+ desoutbuf.length = cipher.ciphertext.length;
+
len_buf[0] = (len & 0xff000000) >> 24;
len_buf[1] = (len & 0xff0000) >> 16;
len_buf[2] = (len & 0xff00) >> 8;
@@ -891,6 +963,7 @@ static int v5_des_write(fd, buf, len)
errno = EIO;
return(-1);
}
+
else return(len);
}
diff --git a/src/appl/bsd/krlogin.c b/src/appl/bsd/krlogin.c
index 54d048b65..0bfb3ef57 100644
--- a/src/appl/bsd/krlogin.c
+++ b/src/appl/bsd/krlogin.c
@@ -19,6 +19,32 @@
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ *
+ * 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 FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. FundsXpress makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
#ifndef lint
char copyright[] =
"@(#) Copyright (c) 1983 The Regents of the University of California.\n\
@@ -61,6 +87,11 @@ char copyright[] =
#include <setjmp.h>
#include <netdb.h>
+#ifdef HAVE_SYS_FILIO_H
+/* Solaris needs <sys/filio.h> for FIONREAD */
+#include <sys/filio.h>
+#endif
+
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
@@ -175,6 +206,7 @@ char *getenv();
char *name;
int rem = -1; /* Remote socket fd */
+int do_inband = 0;
char cmdchar = '~';
int eight = 1; /* Default to 8 bit transmission */
int no_local_escape = 0;
@@ -219,6 +251,7 @@ char *host=0; /* external, so it can be
reached from confirm_death() */
krb5_sigtype sigwinch KRB5_PROTOTYPE((int));
+int server_message KRB5_PROTOTYPE((int));
void oob KRB5_PROTOTYPE((void));
krb5_sigtype lostpeer KRB5_PROTOTYPE((int));
#if __STDC__
@@ -593,8 +626,22 @@ main(argc, argv)
#else
try_normal(orig_argv);
#endif
- } else
+ } else {
+ krb5_boolean similar;
+
rcmd_stream_init_krb5(&cred->keyblock, encrypt_flag, 1);
+
+ if (status = krb5_c_enctype_compare(bsd_context, ENCTYPE_DES_CBC_CRC,
+ cred->keyblock.enctype, &similar))
+ try_normal(orig_argv); /* doesn't return */
+
+ if (!similar) {
+ do_inband = 1;
+ if (debug_port)
+ fprintf(stderr, "DEBUG: setting do_inband\n");
+ }
+ }
+
rem = sock;
#else
@@ -1185,15 +1232,16 @@ int rcvcnt;
int rcvstate;
int ppid;
+/* returns 1 if flush, 0 otherwise */
-void oob()
+int server_message(mark)
+ int mark;
{
#ifndef POSIX_TERMIOS
int out = FWRITE;
#endif
- int atmark, n;
+ int n;
int rcvd = 0;
- char waste[RLOGIN_BUFSIZ], mark;
#ifdef POSIX_TERMIOS
struct termios tty;
#else
@@ -1203,9 +1251,7 @@ void oob()
struct sgttyb sb;
#endif
#endif
- mark = 0;
-
- recv(rem, &mark, 1, MSG_OOB);
+
if (mark & TIOCPKT_WINDOW) {
/*
* Let server know about window size changes
@@ -1263,27 +1309,62 @@ void oob()
(void) ioctl(1, TCFLSH, 1);
#endif
#endif
- for (;;) {
- if (ioctl(rem, SIOCATMARK, &atmark) < 0) {
- perror("ioctl");
- break;
- }
- if (atmark)
- break;
- n = read(rem, waste, sizeof (waste));
- if (n <= 0)
- break;
-return;
- }
+ return(1);
}
+
+ return(0);
+}
+
+void oob()
+{
+ char mark;
+ char waste[RLOGIN_BUFSIZ];
+ int atmark;
+
+ mark = 0;
-
+ recv(rem, &mark, 1, MSG_OOB);
+
+ if (server_message(mark)) {
+ if (ioctl(rem, SIOCATMARK, &atmark) < 0) {
+ perror("ioctl");
+ return;
+ }
+ if (!atmark)
+ read(rem, waste, sizeof (waste));
+ }
}
+/* two control messages are defined:
+ a double flag byte of 'o' indicates a one-byte message which is
+ identical to what was once carried out of band.
+
+ a double flag byte of 'q' indicates a zero-byte message. This
+ message is interpreted as two \377 data bytes. This is just a
+ quote rule so that binary data from the server does not confuse the
+ client. */
+
+int control(cp, n)
+ unsigned char *cp;
+ int n;
+{
+ if ((n >= 5) && (cp[2] == 'o') && (cp[3] == 'o')) {
+ if (server_message(cp[4]))
+ return(-5);
+ return(5);
+ } else if ((n >= 4) && (cp[2] == 'q') && (cp[3] == 'q')) {
+ /* this is somewhat of a hack */
+ cp[2] = '\377';
+ cp[3] = '\377';
+ return(2);
+ }
+
+ return(0);
+}
/*
- * reader: read from remote: line -> 1
+ * reader: read from remote: line -> 1
*/
reader(oldmask)
#ifdef POSIX_SIGNALS
@@ -1298,8 +1379,9 @@ reader(oldmask)
int pid = -getpid();
#endif
fd_set readset, excset, writeset;
- int n, remaining;
+ int n, remaining, left;
char *bufp = rcvbuf;
+ char *cp;
#ifdef POSIX_SIGNALS
struct sigaction sa;
@@ -1326,24 +1408,23 @@ fd_set readset, excset, writeset;
#endif /* POSIX_SIGNALS */
for (;;) {
- if ((remaining = rcvcnt - (bufp - rcvbuf)) > 0)
- {
+ if ((remaining = rcvcnt - (bufp - rcvbuf)) > 0) {
FD_SET(1,&writeset);
rcvstate = WRITING;
FD_CLR(rem, &readset);
+ } else {
+ bufp = rcvbuf;
+ rcvcnt = 0;
+ rcvstate = READING;
+ FD_SET(rem,&readset);
+ FD_CLR(1,&writeset);
}
- else {
-
- bufp = rcvbuf;
- rcvcnt = 0;
- rcvstate = READING;
- FD_SET(rem,&readset);
- FD_CLR(1,&writeset);
- }
- FD_SET(rem,&excset);
+ if (!do_inband)
+ FD_SET(rem,&excset);
if (select(rem+1, &readset, &writeset, &excset, 0) > 0 ) {
- if (FD_ISSET(rem, &excset))
- oob();
+ if (!do_inband)
+ if (FD_ISSET(rem, &excset))
+ oob();
if (FD_ISSET(1,&writeset)) {
n = write(1, bufp, remaining);
if (n < 0) {
@@ -1359,6 +1440,30 @@ fd_set readset, excset, writeset;
return (0);
if (rcvcnt < 0)
goto error;
+
+ if (do_inband) {
+ for (cp = rcvbuf; cp < rcvbuf+rcvcnt-1; cp++) {
+ if (cp[0] == '\377' &&
+ cp[1] == '\377') {
+ left = (rcvbuf+rcvcnt) - cp;
+ n = control(cp, left);
+ if (n < 0) {
+ left -= (-n);
+ rcvcnt = 0;
+ /* flush before, and (-n) bytes */
+ if (left > 0)
+ memmove(rcvbuf, cp+(-n), left);
+ cp = rcvbuf-1;
+ } else if (n) {
+ left -= n;
+ rcvcnt -= n;
+ if (left > 0)
+ memmove(cp, cp+n, left);
+ cp--;
+ }
+ }
+ }
+ }
}
} else
error:
diff --git a/src/appl/bsd/krlogind.c b/src/appl/bsd/krlogind.c
index bd376ff09..f43389719 100644
--- a/src/appl/bsd/krlogind.c
+++ b/src/appl/bsd/krlogind.c
@@ -19,6 +19,32 @@
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ *
+ * 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 FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. FundsXpress makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
#ifndef lint
char copyright[] =
"@(#) Copyright (c) 1983 The Regents of the University of California.\n\
@@ -266,6 +292,7 @@ char *krusername = 0;
char term[64];
char rhost_name[128];
krb5_principal client;
+int do_inband = 0;
int reapchild();
char *progname;
@@ -837,6 +864,31 @@ unsigned char oobdata[] = {TIOCPKT_WINDOW};
char oobdata[] = {0};
#endif
+int sendoob(fd, byte)
+ int fd;
+ char *byte;
+{
+ char message[5];
+ int cc;
+
+ if (do_inband) {
+ message[0] = '\377';
+ message[1] = '\377';
+ message[2] = 'o';
+ message[3] = 'o';
+ message[4] = *byte;
+
+ cc = rcmd_stream_write(fd, message, sizeof(message));
+ while (cc < 0 && ((errno == EWOULDBLOCK) || (errno == EAGAIN))) {
+ /* also shouldn't happen */
+ sleep(5);
+ cc = rcmd_stream_write(fd, message, sizeof(message));
+ }
+ } else {
+ send(fd, byte, 1, MSG_OOB);
+ }
+}
+
/*
* Handle a "control" request (signaled by magic being present)
* in the data stream. For now, we are only willing to handle
@@ -880,7 +932,7 @@ int control(pty, cp, n)
void protocol(f, p)
int f, p;
{
- unsigned char pibuf[BUFSIZ], fibuf[BUFSIZ], *pbp, *fbp;
+ unsigned char pibuf[BUFSIZ], qpibuf[BUFSIZ*2], fibuf[BUFSIZ], *pbp, *fbp;
register pcc = 0, fcc = 0;
int cc;
char cntl;
@@ -915,7 +967,7 @@ void protocol(f, p)
signal(SIGTTOU, SIG_IGN);
#endif
#ifdef TIOCSWINSZ
- send(f, oobdata, 1, MSG_OOB); /* indicate new rlogin */
+ sendoob(f, oobdata);
#endif
for (;;) {
fd_set ibits, obits, ebits;
@@ -933,7 +985,6 @@ void protocol(f, p)
FD_SET(f, &obits);
else
FD_SET(p, &ibits);
- FD_SET(p, &ebits);
if (select(8*sizeof(ibits), &ibits, &obits, &ebits, 0) < 0) {
if (errno == EINTR)
@@ -941,43 +992,32 @@ void protocol(f, p)
fatalperror(f, "select");
}
#define pkcontrol(c) ((c)&(TIOCPKT_FLUSHWRITE|TIOCPKT_NOSTOP|TIOCPKT_DOSTOP))
- if (FD_ISSET(p, &ebits)) {
- cc = read(p, &cntl, 1);
- if (cc == 1 && pkcontrol(cntl)) {
- cntl |= oobdata[0];
- send(f, &cntl, 1, MSG_OOB);
- if (cntl & TIOCPKT_FLUSHWRITE) {
- pcc = 0;
- FD_CLR(p, &ibits);
- }
- }
- }
if (FD_ISSET(f, &ibits)) {
fcc = rcmd_stream_read(f, fibuf, sizeof (fibuf));
- if (fcc < 0 && ((errno == EWOULDBLOCK) || (errno == EAGAIN)))
- fcc = 0;
- else {
+ if (fcc < 0 && ((errno == EWOULDBLOCK) || (errno == EAGAIN))) {
+ fcc = 0;
+ } else {
register unsigned char *cp;
int left, n;
if (fcc <= 0)
- break;
+ break;
fbp = fibuf;
- top:
- for (cp = fibuf; cp < fibuf+fcc-1; cp++)
- if (cp[0] == magic[0] &&
- cp[1] == magic[1]) {
- left = fcc - (cp-fibuf);
- n = control(p, cp, left);
- if (n) {
- left -= n;
- if (left > 0)
- memmove(cp, cp+n, left);
- fcc -= n;
- goto top; /* n^2 */
- }
- }
+ for (cp = fibuf; cp < fibuf+fcc-1; cp++) {
+ if (cp[0] == magic[0] &&
+ cp[1] == magic[1]) {
+ left = (fibuf+fcc) - cp;
+ n = control(p, cp, left);
+ if (n) {
+ left -= n;
+ fcc -= n;
+ if (left > 0)
+ memmove(cp, cp+n, left);
+ cp--;
+ }
+ }
+ }
}
}
@@ -992,24 +1032,54 @@ void protocol(f, p)
if (FD_ISSET(p, &ibits)) {
pcc = read(p, pibuf, sizeof (pibuf));
pbp = pibuf;
- if (pcc < 0 && ((errno == EWOULDBLOCK) || (errno == EAGAIN)))
- pcc = 0;
- else if (pcc <= 0)
- break;
+ if (pcc < 0 && ((errno == EWOULDBLOCK) || (errno == EAGAIN))) {
+ pcc = 0;
+ } else if (pcc <= 0) {
+ break;
+ }
#ifdef TIOCPKT
else if (tiocpkt_on) {
- if (pibuf[0] == 0)
- pbp++, pcc--;
- else {
- if (pkcontrol(pibuf[0])) {
- pibuf[0] |= oobdata[0];
- send(f, &pibuf[0], 1, MSG_OOB);
- }
- pcc = 0;
- }
+ if (pibuf[0] == 0) {
+ pbp++, pcc--;
+ } else {
+ if (pkcontrol(pibuf[0])) {
+ pibuf[0] |= oobdata[0];
+ sendoob(f, pibuf);
+ }
+ pcc = 0;
+ }
}
#endif
+
+ /* quote any double-\377's if necessary */
+
+ if (do_inband) {
+ unsigned char *qpbp;
+ int qpcc, i;
+
+ qpbp = qpibuf;
+ qpcc = 0;
+
+ for (i=0; i<pcc;) {
+ if (pbp[i] == 0377u && (i+1)<pcc && pbp[i+1] == 0377u) {
+ qpbp[qpcc] = '\377';
+ qpbp[qpcc+1] = '\377';
+ qpbp[qpcc+2] = 'q';
+ qpbp[qpcc+3] = 'q';
+ i += 2;
+ qpcc += 4;
+ } else {
+ qpbp[qpcc] = pbp[i];
+ i++;
+ qpcc++;
+ }
+ }
+
+ pbp = qpbp;
+ pcc = qpcc;
+ }
}
+
if (FD_ISSET(f, &obits) && pcc > 0) {
cc = rcmd_stream_write(f, pbp, pcc);
if (cc < 0 && ((errno == EWOULDBLOCK) || (errno == EAGAIN))) {
@@ -1411,6 +1481,21 @@ recvauth(valid_checksum)
rcmd_stream_init_krb5(ticket->enc_part2->session, do_encrypt, 1);
+ {
+ krb5_boolean similar;
+
+ if (status = krb5_c_enctype_compare(bsd_context, ENCTYPE_DES_CBC_CRC,
+ ticket->enc_part2->session->enctype,
+ &similar))
+ return(status);
+
+ if (!similar) {
+ do_inband = 1;
+ syslog(LOG_DEBUG, "setting do_inband");
+ }
+ }
+
+
getstr(netf, rusername, sizeof(rusername), "remuser");
if ((status = krb5_unparse_name(bsd_context, client, &krusername)))
diff --git a/src/appl/bsd/login.c b/src/appl/bsd/login.c
index cb18f4c2c..c8017cc77 100644
--- a/src/appl/bsd/login.c
+++ b/src/appl/bsd/login.c
@@ -48,6 +48,7 @@ char copyright[] =
*/
#define KRB5_GET_TICKETS
int login_krb5_get_tickets = 1;
+
#ifdef KRB5_KRB4_COMPAT
#define KRB4_GET_TICKETS
int login_krb4_get_tickets = 0;
@@ -56,6 +57,7 @@ int login_krb4_convert = 0;
#define KRB_RUN_AKLOG
int login_krb_run_aklog = 0;
#endif /* KRB5_KRB4_COMPAT */
+
int login_accept_passwd = 0;
/*
@@ -189,10 +191,10 @@ typedef sigtype (*handler)();
#ifndef HAVE_KRB_GET_ERR_TEXT
-static const char * krb_get_err_text(kerror)
- int kerror;
+static const char *krb_get_err_text(kerror)
+ int kerror;
{
- return krb_err_txt[kerror];
+ return krb_err_txt[kerror];
}
#endif /*HAVE_KRB_GET_ERR_TEXT*/
@@ -326,52 +328,58 @@ typedef krb5_sigtype sigtype;
#ifndef HAVE_INITGROUPS
static int initgroups(char* name, gid_t basegid) {
- gid_t others[NGROUPS_MAX+1];
- int ngrps;
+ gid_t others[NGROUPS_MAX+1];
+ int ngrps;
- others[0] = basegid;
- ngrps = getgroups(NGROUPS_MAX, others+1);
- return setgroups(ngrps+1, others);
+ others[0] = basegid;
+ ngrps = getgroups(NGROUPS_MAX, others+1);
+ return setgroups(ngrps+1, others);
}
#endif
-#ifdef KRB5_GET_TICKETS
static struct login_confs {
- char *flagname;
- int *flag;
+ char *flagname;
+ int *flag;
} login_conf_set[] = {
- "krb5_get_tickets", &login_krb5_get_tickets,
+#ifdef KRB5_GET_TICKETS
+ "krb5_get_tickets", &login_krb5_get_tickets,
+#endif
#ifdef KRB5_KRB4_COMPAT
- "krb4_get_tickets", &login_krb4_get_tickets,
- "krb4_convert", &login_krb4_convert,
- "krb4_run_aklog", &login_krb_run_aklog,
+ "krb4_get_tickets", &login_krb4_get_tickets,
+ "krb4_convert", &login_krb4_convert,
+ "krb4_run_aklog", &login_krb_run_aklog,
#endif /* KRB5_KRB4_COMPAT */
};
+
static char *conf_yes[] = {
- "y", "yes", "true", "t", "1", "on",
- 0
+ "y", "yes", "true", "t", "1", "on",
+ 0
};
+
static char *conf_no[] = {
- "n", "no", "false", "nil", "0", "off",
- 0
+ "n", "no", "false", "nil", "0", "off",
+ 0
};
+
/* 1 = true, 0 = false, -1 = ambiguous */
static int conf_affirmative(s)
- char *s;
+ char *s;
{
- char **p;
- for(p=conf_yes; *p; p++) {
- if (!strcasecmp(*p,s))
- return 1;
- }
- for(p=conf_no; *p; p++) {
- if (!strcasecmp(*p,s))
- return 0;
- }
- /* ambiguous */
- return -1;
+ char **p;
+
+ for(p=conf_yes; *p; p++) {
+ if (!strcasecmp(*p,s))
+ return 1;
+ }
+
+ for(p=conf_no; *p; p++) {
+ if (!strcasecmp(*p,s))
+ return 0;
+ }
+
+ /* ambiguous */
+ return -1;
}
-#endif /* KRB5_GET_TICKETS */
#ifdef KRB5_GET_TICKETS
krb5_data tgtname = {
@@ -381,46 +389,43 @@ krb5_data tgtname = {
};
#endif
-#ifdef KRB5_GET_TICKETS
/* get flags (listed above) from the profile */
void login_get_kconf(k)
- krb5_context k;
+ krb5_context k;
{
- int i, max_i;
- const char* kconf_names[3];
- char **kconf_val;
- int retval;
-
- max_i = sizeof(login_conf_set)/sizeof(struct login_confs);
- for (i = 0; i<max_i; i++) {
- kconf_names[0] = "login";
- kconf_names[1] = login_conf_set[i].flagname;
- kconf_names[2] = 0;
- retval = profile_get_values(k->profile,
- kconf_names, &kconf_val);
- if (retval) {
- /* ignore most (all?) errors */
- } else if (kconf_val) {
- switch(conf_affirmative(*kconf_val)) {
- case 1:
- *login_conf_set[i].flag = 1;
- break;
- case 0:
- *login_conf_set[i].flag = 0;
- break;
- default:
- case -1:
- com_err("login/kconf", 0,
- "invalid flag value %s for flag %s",
- *kconf_val, kconf_names[1]);
- break;
- }
- }
+ int i, max_i;
+ const char* kconf_names[3];
+ char **kconf_val;
+ int retval;
+
+ max_i = sizeof(login_conf_set)/sizeof(struct login_confs);
+ for (i = 0; i<max_i; i++) {
+ kconf_names[0] = "login";
+ kconf_names[1] = login_conf_set[i].flagname;
+ kconf_names[2] = 0;
+ retval = profile_get_values(k->profile,
+ kconf_names, &kconf_val);
+ if (retval) {
+ /* ignore most (all?) errors */
+ } else if (kconf_val) {
+ switch(conf_affirmative(*kconf_val)) {
+ case 1:
+ *login_conf_set[i].flag = 1;
+ break;
+ case 0:
+ *login_conf_set[i].flag = 0;
+ break;
+ default:
+ case -1:
+ com_err("login/kconf", 0,
+ "invalid flag value %s for flag %s",
+ *kconf_val, kconf_names[1]);
+ break;
+ }
}
+ }
}
-#endif /* KRB5_GET_TICKETS */
-
/* UNIX password support */
struct passwd *pwd;
@@ -475,16 +480,19 @@ int unix_passwd_okay (pass)
#endif
return !strcmp (namep, pwd->pw_passwd);
}
-
+
/* Kerberos support */
#ifdef KRB5_GET_TICKETS
krb5_context kcontext;
krb5_ccache ccache;
-static int got_v5_tickets, got_v4_tickets;
+krb5_creds my_creds;
+static int got_v5_tickets, forwarded_v5_tickets;
char ccfile[MAXPATHLEN+6]; /* FILE:path+\0 */
int krbflag; /* set if tickets have been obtained */
+#endif /* KRB5_GET_TICKETS */
#ifdef KRB4_GET_TICKETS
+static int got_v4_tickets;
AUTH_DAT *kdata = (AUTH_DAT *) NULL;
KTEXT ticket = (KTEXT) NULL;
char tkfile[MAXPATHLEN];
@@ -494,6 +502,7 @@ char realm[REALM_SZ];
void k_init (ttyn)
char *ttyn;
{
+#ifdef KRB5_GET_TICKETS
krb5_error_code retval;
retval = krb5_init_context(&kcontext);
@@ -501,6 +510,7 @@ void k_init (ttyn)
com_err("login", retval, "while initializing krb5");
exit(1);
}
+
krb5_secure_config_files (kcontext);
login_get_kconf(kcontext);
@@ -514,6 +524,7 @@ void k_init (ttyn)
strncpy(ccfile, getenv(KRB5_ENV_CCNAME), sizeof(ccfile));
ccfile[sizeof(ccfile) - 1] = '\0';
}
+#endif
#ifdef KRB4_GET_TICKETS
if (krb_get_lrealm(realm, 1) != KSUCCESS) {
@@ -539,6 +550,7 @@ void k_init (ttyn)
#endif /* BIND_HACK */
}
+#ifdef KRB5_GET_TICKETS
int k5_get_password (user_pwstring, pwsize)
char *user_pwstring;
{
@@ -561,76 +573,23 @@ int k5_get_password (user_pwstring, pwsize)
return 1;
}
-#define KRB5_DEFAULT_LIFE 60*60*10 /* 10 hours */
-int krb5_options = 0;
-krb5_deltat krb5_ticket_lifetime = KRB5_DEFAULT_LIFE;
-
int try_krb5 (me_p, pass)
krb5_principal *me_p;
char *pass;
{
krb5_error_code code;
- krb5_principal server, me;
- krb5_creds my_creds;
- krb5_timestamp now;
- krb5_deltat lifetime = krb5_ticket_lifetime;
-
- /* set up credential cache -- obeying KRB5_ENV_CCNAME
- set earlier */
- /* (KRB5_ENV_CCNAME == "KRB5CCNAME" via osconf.h) */
- if ((code = krb5_cc_default(kcontext, &ccache))) {
- com_err("login", code, "while getting default ccache");
- return 0;
- }
- /* setup code from v5 kinit */
- memset((char *)&my_creds, 0, sizeof(my_creds));
+ krb5_principal me;
- code = krb5_parse_name (kcontext, username, &me);
- if (code) {
+ if (code = krb5_parse_name(kcontext, username, &me)) {
com_err ("login", code, "when parsing name %s",username);
return 0;
}
- *me_p = my_creds.client = me;
- code = krb5_cc_initialize (kcontext, ccache, me);
- if (code) {
- com_err ("login", code,
- "when initializing cache");
- return 0;
- }
+ *me_p = me;
- code = krb5_build_principal_ext(kcontext, &server,
- krb5_princ_realm(kcontext, me)->length,
- krb5_princ_realm(kcontext, me)->data,
- tgtname.length, tgtname.data,
- krb5_princ_realm(kcontext, me)->length,
- krb5_princ_realm(kcontext, me)->data,
- 0);
- if (code) {
- com_err("login", code,
- "while building server name");
- goto nuke_ccache;
- }
-
- my_creds.server = server;
- code = krb5_timeofday(kcontext, &now);
- if (code) {
- com_err("login", code,
- "while getting time of day");
- goto nuke_ccache;
- }
- my_creds.times.starttime = 0; /* start timer when
- request gets to KDC */
- my_creds.times.endtime = now + lifetime;
- my_creds.times.renew_till = 0;
-
- code = krb5_get_in_tkt_with_password(kcontext, krb5_options,
- 0, NULL, 0 /*preauth*/,
- pass,
- ccache,
- &my_creds, 0);
-
- if (code) {
+ if (code = krb5_get_init_creds_password(kcontext, &my_creds, me, pass,
+ krb5_prompter_posix, NULL,
+ 0, NULL, NULL)) {
if (code == KRB5KRB_AP_ERR_BAD_INTEGRITY)
fprintf (stderr,
"%s: Kerberos password incorrect\n",
@@ -638,17 +597,12 @@ int try_krb5 (me_p, pass)
else
com_err ("login", code,
"while getting initial credentials");
- nuke_ccache:
- krb5_cc_destroy (kcontext, ccache);
return 0;
- } else {
- /* get_name pulls out just the name not the
- type */
- strncpy(ccfile, krb5_cc_get_name(kcontext, ccache), sizeof(ccfile));
- ccfile[sizeof(ccfile) - 1] = '\0';
- krbflag = got_v5_tickets = 1;
- return 1;
}
+
+ krbflag = got_v5_tickets = 1;
+
+ return 1;
}
int have_v5_tickets (me)
@@ -663,6 +617,7 @@ int have_v5_tickets (me)
krbflag = 1;
return 1;
}
+#endif /* KRB5_GET_TICKETS */
#ifdef KRB4_CONVERT
try_convert524 (kcontext, me)
@@ -675,8 +630,6 @@ try_convert524 (kcontext, me)
krb5_creds increds, *v5creds;
CREDENTIALS v4creds;
- if (!got_v5_tickets)
- return 0;
/* or do this directly with krb524_convert_creds_kdc */
krb524_init_ets(kcontext);
@@ -886,162 +839,23 @@ EGRESS:
}
#endif /* KRB4_GET_TICKETS */
-/* call already conditionalized on login_krb5_get_tickets */
-/*
- * Verify the Kerberos ticket-granting ticket just retrieved for the
- * user. If the Kerberos server doesn't respond, assume the user is
- * trying to fake us out (since we DID just get a TGT from what is
- * supposedly our KDC). If the host/<host> service is unknown (i.e.,
- * the local keytab doesn't have it), let her in.
- *
- * Returns 1 for confirmation, -1 for failure, 0 for uncertainty.
- */
-int verify_krb_v5_tgt (c)
- krb5_context c;
+void destroy_tickets()
{
- char phost[BUFSIZ];
- krb5_ccache ccdef;
- int retval, have_keys;
- krb5_principal princ;
- krb5_keyblock *kb = 0;
- krb5_error_code krbval;
- krb5_data packet;
- krb5_auth_context auth_context = NULL;
- krb5_ticket *ticket = NULL;
-
- /* XXX This is to work around a library bug. I'm not sure if it's
- been fixed for beta-7, so leave this in for now. Remove it (and
- fix the bug if necessary) after beta-7 ships.
-
- Whoever wrote that comment didn't mention what the bug is! Ted
- says it is something about the starttime of the ticket and
- "now" being equal. He thinks it is fixed, but isn't sure.
- */
- sleep(2);
-
- /* get the server principal for the local host */
- /* (use defaults of "host" and canonicalized local name) */
- krbval = krb5_sname_to_principal(c, 0, 0, KRB5_NT_SRV_HST, &princ);
- if (krbval) {
- com_err ("login", krbval, "constructing local service name");
- return -1;
- }
+#ifdef KRB5_GET_TICKETS
+ krb5_ccache cache;
+ krb5_error_code retval;
- /* since krb5_sname_to_principal has done the work for us, just
- extract the name directly */
- strncpy(phost, krb5_princ_component(c, princ, 1)->data, sizeof(phost));
- phost[sizeof(phost) - 1] = '\0';
-
- /* Do we have host/<host> keys? */
- /* (use default keytab, kvno IGNORE_VNO to get the first match,
- and enctype is currently ignored anyhow.) */
- krbval = krb5_kt_read_service_key (c, NULL, princ, 0, ENCTYPE_DES_CBC_CRC, &kb);
- if (kb)
- krb5_free_keyblock (c, kb);
- /* any failure means we don't have keys at all. */
- have_keys = krbval ? 0 : 1;
-
- /* set up credential cache -- obeying KRB5_ENV_CCNAME set earlier */
- /* (KRB5_ENV_CCNAME == "KRB5CCNAME" via osconf.h) */
- if (krbval = krb5_cc_default(c, &ccdef)) {
- com_err("login", krbval, "while getting default ccache");
- return -1;
- }
- /* talk to the kdc and construct the ticket */
- krbval = krb5_mk_req(c, &auth_context, 0, "host", phost,
- 0, ccdef, &packet);
- /* wipe the auth context for mk_req */
- if (auth_context) {
- krb5_auth_con_free(c, auth_context);
- auth_context = NULL;
- }
- if (krbval == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN) {
- /* we have a service key, so something should be
- in the database, therefore this error packet could
- have come from an attacker. */
- if (have_keys) { retval = -1; goto EGRESS; }
- /* but if it is unknown and we've got no key, we don't
- have any security anyhow, so it is ok. */
- else { retval = 0; goto EGRESS; }
- }
- else if (krbval) {
- com_err("login", krbval,
- "Unable to verify Kerberos V5 TGT: %s", phost);
-#ifndef SYSLOG42
- syslog (LOG_NOTICE|LOG_AUTH, "Kerberos V5 TGT bad: %s",
- error_message(krbval));
-#endif
- retval = -1;
- goto EGRESS;
- }
- /* got ticket, try to use it */
- krbval = krb5_rd_req(c, &auth_context, &packet,
- princ, NULL, NULL, &ticket);
- if (krbval) {
- if (!have_keys)
- /* The krb5 errors aren't specified well, but I think
- these values cover the cases we expect. */
- switch (krbval) {
- /* no keytab */
- case ENOENT:
- /* keytab found, missing entry */
-#if 0 /* Don't depend on the nameserver for security. Assume that if
- we have a keytab, it must contain the right host/FQDN key. */
- case KRB5_KT_NOTFOUND:
-#endif
- retval = 0;
- break;
- default:
- /* unexpected error: fail */
- retval = -1;
- break;
- }
- else
- /* Any error here is bad. */
- retval = -1;
- com_err("login", krbval, "Unable to verify host ticket");
-#ifndef SYSLOG42
- syslog (LOG_NOTICE|LOG_AUTH, "can't verify v5 ticket: %s; %s\n",
- error_message(krbval),
- retval
- ? "keytab found, assuming failure"
- : "no keytab found, assuming success");
-#endif
- goto EGRESS;
+ if (login_krb5_get_tickets) {
+ if(!krb5_cc_default(kcontext, &cache))
+ krb5_cc_destroy (kcontext, cache);
}
- /*
- * The host/<host> ticket has been received _and_ verified.
- */
- retval = 1;
- /* do cleanup and return */
-EGRESS:
- if (auth_context) krb5_auth_con_free(c, auth_context);
- krb5_free_principal(c, princ);
- /* possibly ticket and packet need freeing here as well */
- /* memset (&ticket, 0, sizeof (ticket)); */
- return retval;
-}
-
-destroy_tickets()
-{
- krb5_context c;
- krb5_ccache cache;
- krb5_error_code retval;
-
-#ifdef KRB5_GET_TICKETS
- if (login_krb5_get_tickets) {
- if(!krb5_cc_default(kcontext, &cache))
- krb5_cc_destroy (kcontext, cache);
- }
#endif
#ifdef KRB4_GET_TICKETS
- if (login_krb4_get_tickets||login_krb4_convert)
+ if (login_krb4_get_tickets || login_krb4_convert)
dest_tkt();
#endif /* KRB4_GET_TICKETS */
}
-#endif /* KRB5_GET_TICKETS */
-
/* AFS support routines */
#ifdef SETPAG
@@ -1086,15 +900,13 @@ static int try_afscall (scall)
void
afs_login ()
{
-#ifdef KRB4_GET_TICKETS
-#ifdef SETPAG
+#if defined(KRB4_GET_TICKETS) && defined(SETPAG)
if (login_krb4_get_tickets && pwd->pw_uid) {
/* Only reset the pag for non-root users. */
/* This allows root to become anything. */
pagflag = try_setpag ();
}
#endif
-#endif /* KRB4_GET_TICKETS */
#ifdef KRB_RUN_AKLOG
if (got_v4_tickets && login_krb_run_aklog) {
/* KPROGDIR is $(prefix)/bin */
@@ -1120,19 +932,19 @@ afs_cleanup ()
try_unlog ();
#endif
}
-
+
/* Main routines */
#define EXCL_AUTH_TEST if (rflag || kflag || Kflag || eflag || fflag ) { \
- fprintf(stderr, \
- "login: only one of -r, -k, -K, -e, -F, and -f allowed.\n"); \
- exit(1);\
- }
+ fprintf(stderr, \
+ "login: only one of -r, -k, -K, -e, -F, and -f allowed.\n"); \
+ exit(1); \
+}
#define EXCL_HOST_TEST if (rflag || kflag || Kflag || hflag) { \
- fprintf(stderr, \
- "login: only one of -r, -k, -K, and -h allowed.\n"); \
- exit(1);\
- }
+ fprintf(stderr, \
+ "login: only one of -r, -k, -K, and -h allowed.\n"); \
+ exit(1); \
+}
static void
read_env_vars_from_file (filename)
@@ -1142,7 +954,7 @@ read_env_vars_from_file (filename)
char *p, *eq;
char tbuf[MAXPATHLEN+2];
- if ((fp = fopen("/etc/environment", "r")) != NULL) {
+ if ((fp = fopen(filename, "r")) != NULL) {
while (fgets(tbuf, sizeof(tbuf), fp)) {
if (tbuf[0] == '#')
continue;
@@ -1176,467 +988,480 @@ log_repeated_failures (tty, hostname)
tty, hostname, UT_NAMESIZE,
username);
#endif
- }
- else
+ } else {
syslog(LOG_ERR,
"REPEATED LOGIN FAILURES ON %s, %.*s",
tty, UT_NAMESIZE, username);
+ }
}
int main(argc, argv)
- int argc;
- char **argv;
+ int argc;
+ char **argv;
{
- extern int optind;
- extern char *optarg, **environ;
- struct group *gr;
- int ch;
- char *p;
- int fflag, hflag, pflag, rflag, cnt;
- int kflag, Kflag, eflag;
- int quietlog, passwd_req, ioctlval;
- sigtype timedout();
- char *domain, **envinit, *ttyn, *tty;
- char tbuf[MAXPATHLEN + 2];
- char *ttyname(), *stypeof(), *crypt(), *getpass();
- time_t login_time;
- int retval;
-int rewrite_ccache = 1; /*try to write out ccache*/
+ extern int optind;
+ extern char *optarg, **environ;
+ struct group *gr;
+ int ch;
+ char *p;
+ int fflag, hflag, pflag, rflag, cnt;
+ int kflag, Kflag, eflag;
+ int quietlog, passwd_req, ioctlval;
+ sigtype timedout();
+ char *domain, **envinit, *ttyn, *tty;
+ char tbuf[MAXPATHLEN + 2];
+ char *ttyname(), *stypeof(), *crypt(), *getpass();
+ time_t login_time;
+ int retval;
+ int rewrite_ccache = 1; /*try to write out ccache*/
#ifdef KRB5_GET_TICKETS
- krb5_principal me;
- krb5_creds save_v5creds;
+ krb5_principal me;
+ krb5_creds save_v5creds;
+ krb5_ccache xtra_creds = NULL;
#endif
#ifdef KRB4_GET_TICKETS
- CREDENTIALS save_v4creds;
+ CREDENTIALS save_v4creds;
#endif
- char *ccname = 0; /* name of forwarded cache */
- char *tz = 0;
+ char *ccname = 0; /* name of forwarded cache */
+ char *tz = 0;
- off_t lseek();
- handler sa;
+ off_t lseek();
+ handler sa;
- handler_init (sa, timedout);
- handler_set (SIGALRM, sa);
- (void)alarm((u_int)timeout);
+ handler_init (sa, timedout);
+ handler_set (SIGALRM, sa);
+ (void)alarm((u_int)timeout);
- handler_init (sa, SIG_IGN);
- handler_set (SIGQUIT, sa);
- handler_set (SIGINT, sa);
- setpriority(PRIO_PROCESS, 0, 0 + PRIO_OFFSET);
+ handler_init (sa, SIG_IGN);
+ handler_set (SIGQUIT, sa);
+ handler_set (SIGINT, sa);
+ setpriority(PRIO_PROCESS, 0, 0 + PRIO_OFFSET);
#ifdef OQUOTA
- (void)quota(Q_SETUID, 0, 0, 0);
+ (void)quota(Q_SETUID, 0, 0, 0);
#endif
- /*
- * -p is used by getty to tell login not to destroy the environment
- * -r is used by rlogind to cause the autologin protocol;
- * -f is used to skip a second login authentication
- * -F is used to skip a second login authentication, allows login as root
- * -e is used to skip a second login authentication, but allows
- * login as root.
- * -h is used by other servers to pass the name of the
- * remote host to login so that it may be placed in utmp and wtmp
- * -k is used by klogind to cause the Kerberos V4 autologin protocol;
- * -K is used by klogind to cause the Kerberos V4 autologin
- * protocol with restricted access.
- */
- (void)gethostname(tbuf, sizeof(tbuf));
- domain = strchr(tbuf, '.');
-
- fflag = hflag = pflag = rflag = kflag = Kflag = eflag = 0;
- passwd_req = 1;
- while ((ch = getopt(argc, argv, "Ffeh:pr:k:K:")) != -1)
- switch (ch) {
- case 'f':
- EXCL_AUTH_TEST;
- fflag = 1;
- break;
- case 'F':
- EXCL_AUTH_TEST;
- fflag = 1;
- break;
- case 'h':
- EXCL_HOST_TEST;
- if (getuid()) {
- fprintf(stderr,
- "login: -h for super-user only.\n");
- exit(1);
- }
- hflag = 1;
- if (domain && (p = strchr(optarg, '.')) &&
- strcmp(p, domain) == 0)
- *p = 0;
- hostname = optarg;
- break;
- case 'p':
- pflag = 1;
- break;
- case 'r':
- EXCL_AUTH_TEST;
- EXCL_HOST_TEST;
- if (getuid()) {
- fprintf(stderr,
- "login: -r for super-user only.\n");
- exit(1);
- }
- /* "-r hostname" must be last args */
- if (optind != argc) {
- fprintf(stderr, "Syntax error.\n");
- exit(1);
- }
- rflag = 1;
- passwd_req = (doremotelogin(optarg) == -1);
- if (domain && (p = strchr(optarg, '.')) &&
- !strcmp(p, domain))
- *p = '\0';
- hostname = optarg;
- break;
+ /*
+ * -p is used by getty to tell login not to destroy the environment
+ * -r is used by rlogind to cause the autologin protocol;
+ * -f is used to skip a second login authentication
+ * -F is used to skip a second login authentication, allows login as root
+ * -e is used to skip a second login authentication, but allows
+ * login as root.
+ * -h is used by other servers to pass the name of the
+ * remote host to login so that it may be placed in utmp and wtmp
+ * -k is used by klogind to cause the Kerberos V4 autologin protocol;
+ * -K is used by klogind to cause the Kerberos V4 autologin
+ * protocol with restricted access.
+ */
+ (void)gethostname(tbuf, sizeof(tbuf));
+ domain = strchr(tbuf, '.');
+
+ fflag = hflag = pflag = rflag = kflag = Kflag = eflag = 0;
+ passwd_req = 1;
+ while ((ch = getopt(argc, argv, "Ffeh:pr:k:K:")) != -1)
+ switch (ch) {
+ case 'f':
+ EXCL_AUTH_TEST;
+ fflag = 1;
+ break;
+ case 'F':
+ EXCL_AUTH_TEST;
+ fflag = 1;
+ break;
+ case 'h':
+ EXCL_HOST_TEST;
+ if (getuid()) {
+ fprintf(stderr,
+ "login: -h for super-user only.\n");
+ exit(1);
+ }
+ hflag = 1;
+ if (domain && (p = strchr(optarg, '.')) && strcmp(p, domain) == 0)
+ *p = 0;
+ hostname = optarg;
+ break;
+ case 'p':
+ pflag = 1;
+ break;
+ case 'r':
+ EXCL_AUTH_TEST;
+ EXCL_HOST_TEST;
+ if (getuid()) {
+ fprintf(stderr,
+ "login: -r for super-user only.\n");
+ exit(1);
+ }
+ /* "-r hostname" must be last args */
+ if (optind != argc) {
+ fprintf(stderr, "Syntax error.\n");
+ exit(1);
+ }
+ rflag = 1;
+ passwd_req = (doremotelogin(optarg) == -1);
+ if (domain && (p = strchr(optarg, '.')) && !strcmp(p, domain))
+ *p = '\0';
+ hostname = optarg;
+ break;
#ifdef KRB4_KLOGIN
- case 'k':
- case 'K':
- EXCL_AUTH_TEST;
- EXCL_HOST_TEST;
- if (getuid()) {
- fprintf(stderr,
- "login: -%c for super-user only.\n", ch);
- exit(1);
- }
- /* "-k hostname" must be last args */
- if (optind != argc) {
- fprintf(stderr, "Syntax error.\n");
- exit(1);
- }
- if (ch == 'K')
- Kflag = 1;
- else
- kflag = 1;
- passwd_req = (do_krb_login(optarg,
- Kflag ? 1 : 0) == -1);
- if (domain && (p = strchr(optarg, '.')) &&
- !strcmp(p, domain))
- *p = '\0';
- hostname = optarg;
- break;
+ case 'k':
+ case 'K':
+ EXCL_AUTH_TEST;
+ EXCL_HOST_TEST;
+ if (getuid()) {
+ fprintf(stderr,
+ "login: -%c for super-user only.\n", ch);
+ exit(1);
+ }
+ /* "-k hostname" must be last args */
+ if (optind != argc) {
+ fprintf(stderr, "Syntax error.\n");
+ exit(1);
+ }
+ if (ch == 'K')
+ Kflag = 1;
+ else
+ kflag = 1;
+ passwd_req = (do_krb_login(optarg, Kflag ? 1 : 0) == -1);
+ if (domain &&
+ (p = strchr(optarg, '.')) &&
+ (!strcmp(p, domain)))
+ *p = '\0';
+ hostname = optarg;
+ break;
#endif /* KRB4_KLOGIN */
- case 'e':
- EXCL_AUTH_TEST;
- if (getuid()) {
- fprintf(stderr,
- "login: -e for super-user only.\n");
- exit(1);
- }
- eflag = 1;
- passwd_req = 0;
- break;
- case '?':
- default:
- fprintf(stderr, "usage: login [-fp] [username]\n");
- exit(1);
- }
- argc -= optind;
- argv += optind;
- if (*argv)
- username = *argv;
+ case 'e':
+ EXCL_AUTH_TEST;
+ if (getuid()) {
+ fprintf(stderr,
+ "login: -e for super-user only.\n");
+ exit(1);
+ }
+ eflag = 1;
+ passwd_req = 0;
+ break;
+ case '?':
+ default:
+ fprintf(stderr, "usage: login [-fp] [username]\n");
+ exit(1);
+ }
+ argc -= optind;
+ argv += optind;
+ if (*argv)
+ username = *argv;
#if !defined(POSIX_TERMIOS) && defined(TIOCLSET)
- ioctlval = 0;
- /* Only do this we we're not using POSIX_TERMIOS */
- (void)ioctl(0, TIOCLSET, (char *)&ioctlval);
+ ioctlval = 0;
+ /* Only do this we we're not using POSIX_TERMIOS */
+ (void)ioctl(0, TIOCLSET, (char *)&ioctlval);
#endif
#ifdef TIOCNXCL
- (void)ioctl(0, TIOCNXCL, (char *)0);
+ (void)ioctl(0, TIOCNXCL, (char *)0);
#endif
- ioctlval = fcntl(0, F_GETFL);
+ ioctlval = fcntl(0, F_GETFL);
#ifdef O_NONBLOCK
- ioctlval &= ~O_NONBLOCK;
+ ioctlval &= ~O_NONBLOCK;
#endif
#ifdef O_NDELAY
- ioctlval &= ~O_NDELAY;
+ ioctlval &= ~O_NDELAY;
#endif
- (void)fcntl(0, F_SETFL, ioctlval);
+ (void)fcntl(0, F_SETFL, ioctlval);
/*
* If talking to an rlogin process, propagate the terminal type and
* baud rate across the network.
*/
- if (eflag)
- lgetstr(term, sizeof(term), "Terminal type");
- else if (!(kflag || Kflag )) /*Preserve terminal if not read over net */
- {
- if (getenv("TERM")) {
- strncpy(term, getenv("TERM"), sizeof(term));
- term[sizeof(term) - 1] = '\0';
- }
- }
+ if (eflag) {
+ lgetstr(term, sizeof(term), "Terminal type");
+ } else if (!(kflag || Kflag)) {/* Preserve terminal if not read over net */
+ if (getenv("TERM")) {
+ strncpy(term, getenv("TERM"), sizeof(term));
+ term[sizeof(term) - 1] = '\0';
+ }
+ }
- term_init (rflag || kflag || Kflag || eflag);
+ term_init (rflag || kflag || Kflag || eflag);
- for (cnt = getdtablesize(); cnt > 2; cnt--)
- (void) close(cnt);
+ for (cnt = getdtablesize(); cnt > 2; cnt--)
+ (void) close(cnt);
- ttyn = ttyname(0);
- if (ttyn == NULL || *ttyn == '\0')
- ttyn = "/dev/tty??";
+ ttyn = ttyname(0);
+ if (ttyn == NULL || *ttyn == '\0')
+ ttyn = "/dev/tty??";
- /* This allows for tty names of the form /dev/pts/4 as well */
- if ((tty = strchr(ttyn, '/')) && (tty = strchr(tty+1, '/')))
- ++tty;
- else
- tty = ttyn;
+ /* This allows for tty names of the form /dev/pts/4 as well */
+ if ((tty = strchr(ttyn, '/')) && (tty = strchr(tty+1, '/')))
+ ++tty;
+ else
+ tty = ttyn;
#ifndef LOG_ODELAY /* 4.2 syslog ... */
- openlog("login", 0);
+ openlog("login", 0);
#else
- openlog("login", LOG_ODELAY, LOG_AUTH);
+ openlog("login", LOG_ODELAY, LOG_AUTH);
#endif /* 4.2 syslog */
/******* begin askpw *******/
- /* overall:
- ask for username if we don't have it already
- look it up in local pw or shadow file (to get crypt string)
- ask for password
- try and get v4, v5 tickets with it
- try and use the tickets against the local srvtab
- if the password matches, always let them in
- if the ticket decrypts, let them in.
- v5 needs to work, does v4?
- */
-
+ /* overall:
+ ask for username if we don't have it already
+ look it up in local pw or shadow file (to get crypt string)
+ ask for password
+ try and get v4, v5 tickets with it
+ try and use the tickets against the local srvtab
+ if the password matches, always let them in
+ if the ticket decrypts, let them in.
+ v5 needs to work, does v4?
+ */
+
+ k_init (ttyn);
+
+ for (cnt = 0;; username = NULL) {
#ifdef KRB5_GET_TICKETS
- k_init (ttyn);
-#endif
-
- for (cnt = 0;; username = NULL) {
-#ifdef KRB5_GET_TICKETS
- int kpass_ok,lpass_ok;
- char user_pwstring[MAXPWSIZE];
- /* variables from v5 kinit */
+ int kpass_ok, lpass_ok;
+ char user_pwstring[MAXPWSIZE];
#endif /* KRB5_GET_TICKETS */
- if (username == NULL) {
- fflag = 0;
- getloginname();
- }
-
- lookup_user (username); /* sets pwd */
-
- /* if user not super-user, check for disabled logins */
- if (pwd == NULL || pwd->pw_uid)
- checknologin();
+ if (username == NULL) {
+ fflag = 0;
+ getloginname();
+ }
- /*
- * Allows automatic login by root.
- * If not invoked by root, disallow if the uid's differ.
- */
+ lookup_user(username); /* sets pwd */
- if (fflag && pwd) {
- int uid = (int) getuid();
- passwd_req = (uid && uid != pwd->pw_uid);
- }
+ /* if user not super-user, check for disabled logins */
+ if (pwd == NULL || pwd->pw_uid)
+ checknologin();
- /*
- * If no remote login authentication and a password exists
- * for this user, prompt for one and verify it.
- */
- if (!passwd_req)
- break;
+ /*
+ * Allows automatic login by root.
+ * If not invoked by root, disallow if the uid's differ.
+ */
- if (! unix_needs_passwd ())
- break;
+ if (fflag && pwd) {
+ int uid = (int) getuid();
+ passwd_req = (uid && uid != pwd->pw_uid);
+ }
- /* we have several sets of code:
- 1) get v5 tickets alone -DKRB5_GET_TICKETS
- 2) get v4 tickets alone [** don't! only get them *with* v5 **]
- 3) get both tickets -DKRB5_GET_TICKETS -DKRB4_GET_TICKETS
- 3a) use krb524 calls to get the v4 tickets -DKRB4_CONVERT plus (3).
- 4) get no tickets and use the password file (none of thes defined.)
+ /*
+ * If no remote login authentication and a password exists
+ * for this user, prompt for one and verify it.
+ */
+ if (!passwd_req)
+ break;
+
+ if (!unix_needs_passwd())
+ break;
+
+ /* we have several sets of code:
+ 1) get v5 tickets alone -DKRB5_GET_TICKETS
+ 2) get v4 tickets alone [** don't! only get them *with* v5 **]
+ 3) get both tickets -DKRB5_GET_TICKETS -DKRB4_GET_TICKETS
+ 3a) use krb524 calls to get the v4 tickets -DKRB4_CONVERT plus (3).
+ 4) get no tickets and use the password file (none of thes defined.)
- Likewise we need to (optionally?) test these tickets against local srvtabs.
- */
+ Likewise we need to (optionally?) test these tickets against
+ local srvtabs.
+ */
+
#ifdef KRB5_GET_TICKETS
- if (login_krb5_get_tickets) {
- /* rename these to something more verbose */
- kpass_ok = 0;
- lpass_ok = 0;
-
- setpriority(PRIO_PROCESS, 0, -4 + PRIO_OFFSET);
- if (! k5_get_password (user_pwstring, sizeof (user_pwstring))) {
- goto bad_login;
- }
+ if (login_krb5_get_tickets) {
+ /* rename these to something more verbose */
+ kpass_ok = 0;
+ lpass_ok = 0;
- /* now that we have the password, we've obscured things
- sufficiently, and can avoid trying tickets */
- if (!pwd)
- goto bad_login;
+ setpriority(PRIO_PROCESS, 0, -4 + PRIO_OFFSET);
+ if (! k5_get_password(user_pwstring, sizeof (user_pwstring))) {
+ goto bad_login;
+ }
+
+ /* now that we have the password, we've obscured things
+ sufficiently, and can avoid trying tickets */
+ if (!pwd)
+ goto bad_login;
- lpass_ok = unix_passwd_okay (user_pwstring);
+ lpass_ok = unix_passwd_okay(user_pwstring);
- if (pwd->pw_uid != 0) { /* Don't get tickets for root */
- try_krb5 (&me, user_pwstring);
+ if (pwd->pw_uid != 0) { /* Don't get tickets for root */
+ try_krb5(&me, user_pwstring);
#ifdef KRB4_GET_TICKETS
- if (login_krb4_get_tickets
- && (!got_v5_tickets
- || !login_krb4_convert))
- try_krb4 (me, user_pwstring);
+ if (login_krb4_get_tickets &&
+ !(got_v5_tickets && login_krb4_convert))
+ try_krb4(me, user_pwstring);
+#endif
+ krbflag = (got_v5_tickets
+#ifdef KRB4_GET_TICKETS
+ || got_v4_tickets
#endif
- krbflag = got_v5_tickets || got_v4_tickets;
- memset (user_pwstring, 0, sizeof(user_pwstring));
- /* password wiped, so we can relax */
- setpriority(PRIO_PROCESS, 0, 0 + PRIO_OFFSET);
+ );
+ memset (user_pwstring, 0, sizeof(user_pwstring));
+ /* password wiped, so we can relax */
+ setpriority(PRIO_PROCESS, 0, 0 + PRIO_OFFSET);
+ } else {
+ memset(user_pwstring, 0, sizeof(user_pwstring));
+ setpriority(PRIO_PROCESS, 0, 0 + PRIO_OFFSET);
+ }
+
+ /* Policy: If local password is good, user is good.
+ We really can't trust the Kerberos password,
+ because somebody on the net could spoof the
+ Kerberos server (not easy, but possible).
+ Some sites might want to use it anyways, in
+ which case they should change this line
+ to:
+ if (kpass_ok)
+ */
+
+ if (lpass_ok)
+ break;
+ if (got_v5_tickets) {
+ if (retval = krb5_verify_init_creds(kcontext, &my_creds, NULL,
+ NULL, &xtra_creds,
+ NULL)) {
+ com_err("login", retval, "while verifying initial ticket");
+#ifndef SYSLOG42
+ syslog(LOG_NOTICE|LOG_AUTH,
+ "can't verify v5 ticket: %s\n",
+ error_message(retval));
+#endif
} else {
- memset (user_pwstring, 0, sizeof(user_pwstring));
- setpriority(PRIO_PROCESS, 0, 0 + PRIO_OFFSET);
+ break; /* we're ok */
}
-
- /* Policy: If local password is good, user is good.
- We really can't trust the Kerberos password,
- because somebody on the net could spoof the
- Kerberos server (not easy, but possible).
- Some sites might want to use it anyways, in
- which case they should change this line
- to:
- if (kpass_ok)
- */
- if (lpass_ok)
- break;
- if (got_v5_tickets
- && verify_krb_v5_tgt(kcontext) != -1)
- break; /* we're ok */
+ }
#ifdef KRB4_GET_TICKETS
- if (login_krb4_get_tickets) {
- if (got_v4_tickets
- && ! got_v5_tickets
- && verify_krb_v4_tgt(realm) != -1)
- break; /* we're ok */
- }
+ else if (got_v4_tickets) {
+ if (login_krb4_get_tickets &&
+ (verify_krb_v4_tgt(realm) != -1))
+ break; /* we're ok */
+ }
#endif /* KRB4_GET_TICKETS */
+
bad_login:
- setpriority(PRIO_PROCESS, 0, 0 + PRIO_OFFSET);
- if (krbflag)
- destroy_tickets(); /* clean up tickets if login fails */
+ setpriority(PRIO_PROCESS, 0, 0 + PRIO_OFFSET);
- }
+ if (krbflag)
+ destroy_tickets(); /* clean up tickets if login fails */
+ }
#endif /* KRB5_GET_TICKETS */
+
#ifdef OLD_PASSWD
- p = getpass ("Password:");
- /* conventional password only */
- if (unix_passwd_okay (p))
- break;
+ p = getpass ("Password:");
+ /* conventional password only */
+ if (unix_passwd_okay (p))
+ break;
#endif /* OLD_PASSWD */
- printf("Login incorrect\n");
- if (++cnt >= 5) {
- log_repeated_failures (tty, hostname);
-/* irix has no tichpcl */
+ printf("Login incorrect\n");
+ if (++cnt >= 5) {
+ log_repeated_failures (tty, hostname);
+ /* irix has no tichpcl */
#ifdef TIOCHPCL
- (void)ioctl(0, TIOCHPCL, (char *)0);
+ (void)ioctl(0, TIOCHPCL, (char *)0);
#endif
- sleepexit(1);
- }
- } /* end of password retry loop */
+ sleepexit(1);
+ }
+ } /* end of password retry loop */
- /* committed to login -- turn off timeout */
- (void)alarm((u_int)0);
+ /* committed to login -- turn off timeout */
+ (void) alarm((u_int) 0);
- /*
- * If valid so far and root is logging in, see if root logins on
- * this terminal are permitted.
- *
- * We allow authenticated remote root logins (except -r style)
- */
- if (pwd->pw_uid == 0 && !rootterm(tty) && (passwd_req || rflag)) {
- if (hostname)
+ /*
+ * If valid so far and root is logging in, see if root logins on
+ * this terminal are permitted.
+ *
+ * We allow authenticated remote root logins (except -r style)
+ */
+
+ if (pwd->pw_uid == 0 && !rootterm(tty) && (passwd_req || rflag)) {
+ if (hostname) {
#ifdef UT_HOSTSIZE
- syslog(LOG_ERR, "ROOT LOGIN REFUSED ON %s FROM %.*s",
- tty, UT_HOSTSIZE, hostname);
+ syslog(LOG_ERR, "ROOT LOGIN REFUSED ON %s FROM %.*s",
+ tty, UT_HOSTSIZE, hostname);
#else
- syslog(LOG_ERR, "ROOT LOGIN REFUSED ON %s FROM %s",
- tty, hostname);
+ syslog(LOG_ERR, "ROOT LOGIN REFUSED ON %s FROM %s",
+ tty, hostname);
#endif
- else
- syslog(LOG_ERR, "ROOT LOGIN REFUSED ON %s", tty);
- printf("Login incorrect\n");
- sleepexit(1);
+ } else {
+ syslog(LOG_ERR, "ROOT LOGIN REFUSED ON %s", tty);
}
+ printf("Login incorrect\n");
+ sleepexit(1);
+ }
#ifdef OQUOTA
- if (quota(Q_SETUID, pwd->pw_uid, 0, 0) < 0 && errno != EINVAL) {
- switch(errno) {
- case EUSERS:
- fprintf(stderr,
- "Too many users logged on already.\nTry again later.\n");
- break;
- case EPROCLIM:
- fprintf(stderr,
- "You have too many processes running.\n");
- break;
- default:
- perror("quota (Q_SETUID)");
- }
- sleepexit(0);
+ if (quota(Q_SETUID, pwd->pw_uid, 0, 0) < 0 && errno != EINVAL) {
+ switch(errno) {
+ case EUSERS:
+ fprintf(stderr,
+ "Too many users logged on already.\nTry again later.\n");
+ break;
+ case EPROCLIM:
+ fprintf(stderr,
+ "You have too many processes running.\n");
+ break;
+ default:
+ perror("quota (Q_SETUID)");
}
+ sleepexit(0);
+ }
#endif
- if (chdir(pwd->pw_dir) < 0) {
- printf("No directory %s!\n", pwd->pw_dir);
- if (chdir("/"))
- exit(0);
- pwd->pw_dir = "/";
- printf("Logging in with home = \"/\".\n");
- }
- /* nothing else left to fail -- really log in */
- {
- struct utmp utmp;
-
- login_time = time(&utmp.ut_time);
- if ( (retval = pty_update_utmp(PTY_USER_PROCESS, getpid(), username, ttyn, hostname, PTY_TTYSLOT_USABLE)) < 0 )
- com_err (argv[0], retval, "while updating utmp");
- }
+ if (chdir(pwd->pw_dir) < 0) {
+ printf("No directory %s!\n", pwd->pw_dir);
+ if (chdir("/"))
+ exit(0);
+ pwd->pw_dir = "/";
+ printf("Logging in with home = \"/\".\n");
+ }
- quietlog = access(HUSHLOGIN, F_OK) == 0;
- dolastlog(quietlog, tty);
+ /* nothing else left to fail -- really log in */
+ {
+ struct utmp utmp;
- if (!hflag && !rflag && !kflag && !Kflag && !eflag) { /* XXX */
- static struct winsize win = { 0, 0, 0, 0 };
+ login_time = time(&utmp.ut_time);
+ if ((retval = pty_update_utmp(PTY_USER_PROCESS, getpid(), username,
+ ttyn, hostname,
+ PTY_TTYSLOT_USABLE)) < 0)
+ com_err (argv[0], retval, "while updating utmp");
+ }
- (void)ioctl(0, TIOCSWINSZ, (char *)&win);
- }
+ quietlog = access(HUSHLOGIN, F_OK) == 0;
+ dolastlog(quietlog, tty);
- (void)chown(ttyn, pwd->pw_uid,
- (gr = getgrnam(TTYGRPNAME)) ? gr->gr_gid : pwd->pw_gid);
+ if (!hflag && !rflag && !kflag && !Kflag && !eflag) { /* XXX */
+ static struct winsize win = { 0, 0, 0, 0 };
- (void)chmod(ttyn, 0620);
-#ifdef KRB5_GET_TICKETS
- /* Maybe telnetd got tickets for us? */
- if (!got_v5_tickets && have_v5_tickets (&me))
- got_v5_tickets = 1;
-#endif /* GET_KRB_TICKETS */
+ (void)ioctl(0, TIOCSWINSZ, (char *)&win);
+ }
-#ifdef KRB4_GET_TICKETS
- if ( login_krb4_convert && !got_v4_tickets) {
+ (void)chown(ttyn, pwd->pw_uid,
+ (gr = getgrnam(TTYGRPNAME)) ? gr->gr_gid : pwd->pw_gid);
+ (void)chmod(ttyn, 0620);
- if (got_v5_tickets)
- try_convert524 (kcontext, me);
+#ifdef KRB5_GET_TICKETS
+ /* Maybe telnetd got tickets for us? */
+ if (!got_v5_tickets && have_v5_tickets (&me))
+ forwarded_v5_tickets = 1;
+#endif /* KRB5_GET_TICKETS */
- }
+#if defined(KRB5_GET_TICKETS) && defined(KRB4_CONVERT)
+ if (login_krb4_convert && !got_v4_tickets) {
+ if (got_v5_tickets||forwarded_v5_tickets)
+ try_convert524 (kcontext, me);
+ }
#endif
-#if defined(KRB5_GET_TICKETS) || defined(KRB4_GET_TICKETS)
-#if defined(KRB5_GET_TICKETS) && defined(KRB4_GET_TICKETS)
- if (login_krb4_get_tickets || login_krb5_get_tickets) {
-#elif defined(KRB4_GET_TICKETS)
- if (login_krb4_get_tickets) {
-#else
- if (login_krb5_get_tickets) {
+#ifdef KRB5_GET_TICKETS
+ if (login_krb5_get_tickets)
+ dofork();
+ else
#endif
- /* Fork so that we can call kdestroy */
+#ifdef KRB4_GET_TICKETS
+ if (login_krb4_get_tickets)
dofork();
- }
-#endif /* KRB4_GET_TICKETS */
+#endif
/* If the user's shell does not do job control we should put it in a
different process group than than us, and set the tty process group
@@ -1644,335 +1469,364 @@ int rewrite_ccache = 1; /*try to write out ccache*/
telnetd or rlogind if they don't properly detach from their
controlling tty, which is the case (under SunOS at least.) */
- {
- int p = getpid();
- struct sigaction sa, osa;
+ {
+ int p = getpid();
+ struct sigaction sa, osa;
- /* this will set the PGID to the PID. */
+ /* this will set the PGID to the PID. */
#ifdef HAVE_SETPGID
- if (setpgid(p,p) < 0) perror("login.krb5: setpgid");
+ if (setpgid(p,p) < 0)
+ perror("login.krb5: setpgid");
+#elif defined(SETPGRP_TWOARG)
+ if (setpgrp(p,p) < 0)
+ perror("login.krb5: setpgrp");
#else
-#ifdef SETPGRP_TWOARG
- if (setpgrp(p,p) < 0) perror("login.krb5: setpgrp");
-#else
- if (setpgrp() < 0) perror("login.krb5: setpgrp");
-#endif
+ if (setpgrp() < 0)
+ perror("login.krb5: setpgrp");
#endif
- /* This will cause SIGTTOU to be ignored for the duration
- of the TIOCSPGRP. If this is not done, and the parent's
- process group is the foreground pgrp of the tty, then
- this will suspend the child, which is bad. */
+ /* This will cause SIGTTOU to be ignored for the duration
+ of the TIOCSPGRP. If this is not done, and the parent's
+ process group is the foreground pgrp of the tty, then
+ this will suspend the child, which is bad. */
- sa.sa_flags = 0;
- sa.sa_handler = SIG_IGN;
- sigemptyset(&(sa.sa_mask));
+ sa.sa_flags = 0;
+ sa.sa_handler = SIG_IGN;
+ sigemptyset(&(sa.sa_mask));
- if (sigaction(SIGTTOU, &sa, &osa))
- perror("login.krb5: sigaction(SIGTTOU, SIG_IGN)");
+ if (sigaction(SIGTTOU, &sa, &osa))
+ perror("login.krb5: sigaction(SIGTTOU, SIG_IGN)");
- /* This will set the foreground process group of the
- controlling terminal to this process group (containing
- only this process). */
+ /* This will set the foreground process group of the
+ controlling terminal to this process group (containing
+ only this process). */
#ifdef HAVE_TCSETPGRP
- if (tcsetpgrp(0, p) < 0) perror("login.krb5: tcsetpgrp");
+ if (tcsetpgrp(0, p) < 0)
+ perror("login.krb5: tcsetpgrp");
#else
- if (ioctl(0, TIOCSPGRP, &p) < 0) perror("login.krb5: tiocspgrp");
+ if (ioctl(0, TIOCSPGRP, &p) < 0)
+ perror("login.krb5: tiocspgrp");
#endif
- /* This will reset the SIGTTOU handler */
+ /* This will reset the SIGTTOU handler */
- if (sigaction(SIGTTOU, &osa, NULL))
- perror("login.krb5: sigaction(SIGTTOU, [old handler])");
- }
+ if (sigaction(SIGTTOU, &osa, NULL))
+ perror("login.krb5: sigaction(SIGTTOU, [old handler])");
+ }
- (void)setgid((gid_t) pwd->pw_gid);
- (void) initgroups(username, pwd->pw_gid);
+ (void) setgid((gid_t) pwd->pw_gid);
+ (void) initgroups(username, pwd->pw_gid);
- /*
- * The V5 ccache and V4 ticket file are both created as root.
- * They need to be owned by the user, and chown (a) assumes
- * they are stored in a file and (b) allows a race condition
- * in which a user can delete the file (if the directory
- * sticky bit is not set) and make it a symlink to somewhere
- * else; on some platforms, chown() on a symlink actually
- * changes the owner of the pointed-to file. This is Bad.
- *
- * So, we suck the V5 and V4 krbtgts into memory here, destroy
- * the ccache/ticket file, and recreate them later after the
- * setuid.
- */
+ /*
+ * The V5 ccache and V4 ticket file are both created as root.
+ * They need to be owned by the user, and chown (a) assumes
+ * they are stored in a file and (b) allows a race condition
+ * in which a user can delete the file (if the directory
+ * sticky bit is not set) and make it a symlink to somewhere
+ * else; on some platforms, chown() on a symlink actually
+ * changes the owner of the pointed-to file. This is Bad.
+ *
+ * So, we suck the V5 and V4 krbtgts into memory here, destroy
+ * the ccache/ticket file, and recreate them later after the
+ * setuid.
+ *
+ * With the new v5 api, v5 tickets are kept in memory until written
+ * out after the setuid. However, forwarded tickets still
+ * need to be read in and recreated later
+ */
#ifdef KRB5_GET_TICKETS
- if (got_v5_tickets) {
- krb5_creds mcreds;
-
- memset(&mcreds, 0, sizeof(mcreds));
- memset(&save_v5creds, 0, sizeof(save_v5creds));
-
- mcreds.client = me;
- retval = krb5_build_principal_ext(kcontext, &mcreds.server,
- krb5_princ_realm(kcontext, me)->length,
- krb5_princ_realm(kcontext, me)->data,
- tgtname.length, tgtname.data,
- krb5_princ_realm(kcontext, me)->length,
- krb5_princ_realm(kcontext, me)->data,
- 0);
- if (retval) {
- syslog(LOG_ERR,
- "%s while creating V5 krbtgt principal",
- error_message(retval));
- goto skip_ccache_rewrite;
- }
-
- mcreds.ticket_flags =0;
-
- if (retval = krb5_cc_retrieve_cred(kcontext, ccache,
- 0,
- &mcreds, &save_v5creds)) {
- syslog(LOG_ERR,
- "%s while retrieiving V5 initial ticket for copy",
- error_message(retval));
- skip_ccache_rewrite: rewrite_ccache = 0;
-
- }
- krb5_free_principal(kcontext, mcreds.server);
+ if (forwarded_v5_tickets) {
+ krb5_creds mcreds;
+
+ memset(&mcreds, 0, sizeof(mcreds));
+ memset(&save_v5creds, 0, sizeof(save_v5creds));
+
+ mcreds.client = me;
+ retval =
+ krb5_build_principal_ext(kcontext, &mcreds.server,
+ krb5_princ_realm(kcontext, me)->length,
+ krb5_princ_realm(kcontext, me)->data,
+ tgtname.length, tgtname.data,
+ krb5_princ_realm(kcontext, me)->length,
+ krb5_princ_realm(kcontext, me)->data,
+ 0);
+ if (retval) {
+ syslog(LOG_ERR,
+ "%s while creating V5 krbtgt principal",
+ error_message(retval));
+ rewrite_ccache = 0;
+ } else {
+ mcreds.ticket_flags = 0;
+
+ if (retval = krb5_cc_retrieve_cred(kcontext, ccache, 0,
+ &mcreds, &save_v5creds)) {
+ syslog(LOG_ERR,
+ "%s while retrieiving V5 initial ticket for copy",
+ error_message(retval));
+ rewrite_ccache = 0;
+ }
}
+
+ krb5_free_principal(kcontext, mcreds.server);
+ }
#endif /* KRB5_GET_TICKETS */
+
#ifdef KRB4_GET_TICKETS
- if (got_v4_tickets) {
- memset(&save_v4creds, 0, sizeof(save_v4creds));
-
- retval = krb_get_cred("krbtgt", realm, realm, &save_v4creds);
- if (retval != KSUCCESS) {
- syslog(LOG_ERR,
- "%s while retrieving V4 initial ticket for copy",
- error_message(retval));
- rewrite_ccache = 0;
+ if (got_v4_tickets) {
+ memset(&save_v4creds, 0, sizeof(save_v4creds));
- }
+ retval = krb_get_cred("krbtgt", realm, realm, &save_v4creds);
+ if (retval != KSUCCESS) {
+ syslog(LOG_ERR,
+ "%s while retrieving V4 initial ticket for copy",
+ error_message(retval));
+ rewrite_ccache = 0;
}
+ }
#endif /* KRB4_GET_TICKETS */
-#if defined(KRB5_GET_TICKETS) || defined(KRB4_GET_TICKETS)
- if (got_v5_tickets || got_v4_tickets)
- destroy_tickets();
+
+#ifdef KRB5_GET_TICKETS
+ if (forwarded_v5_tickets)
+ destroy_tickets();
+ else
+#endif
+#ifdef KRB4_GET_TICKETS
+ if (got_v4_tickets)
+ destroy_tickets();
#endif
#ifdef OQUOTA
- quota(Q_DOWARN, pwd->pw_uid, (dev_t)-1, 0);
+ quota(Q_DOWARN, pwd->pw_uid, (dev_t)-1, 0);
#endif
#ifdef HAVE_SETLOGIN
- if (setlogin(pwd->pw_name) < 0)
- syslog(LOG_ERR, "setlogin() failure %d",errno);
+ if (setlogin(pwd->pw_name) < 0)
+ syslog(LOG_ERR, "setlogin() failure %d",errno);
#endif
#ifdef HAVE_SETLUID
- /*
- * If we're on a system which keeps track of login uids, then
- * attempt to set the login uid, but don't get too unhappy when/if
- * it doesn't succeed.
- */
- if ((uid_t) getluid() < (uid_t) 0) {
- setluid((uid_t) pwd->pw_uid);
- }
+ /*
+ * If we're on a system which keeps track of login uids, then
+ * attempt to set the login uid, but don't get too unhappy when/if
+ * it doesn't succeed.
+ */
+ if ((uid_t) getluid() < (uid_t) 0) {
+ setluid((uid_t) pwd->pw_uid);
+ }
#endif /* HAVE_SETLUID */
#ifdef _IBMR2
- setuidx(ID_LOGIN, pwd->pw_uid);
+ setuidx(ID_LOGIN, pwd->pw_uid);
#endif
- /* This call MUST succeed */
- if(setuid((uid_t) pwd->pw_uid) < 0) {
- perror("setuid");
- sleepexit(1);
- }
+ /* This call MUST succeed */
+ if (setuid((uid_t) pwd->pw_uid) < 0) {
+ perror("setuid");
+ sleepexit(1);
+ }
+
+ /*
+ * We are the user now. Re-create the destroyed ccache and
+ * ticket file.
+ */
- /*
- * We are the user now. Re-create the destroyed ccache and
- * ticket file.
- */
#ifdef KRB5_GET_TICKETS
- if (got_v5_tickets && rewrite_ccache) {
- retval = krb5_cc_initialize (kcontext, ccache, me);
- if (retval) {
- syslog(LOG_ERR,
- "%s while re-initializing V5 ccache as user",
- error_message(retval));
- goto skip_ccache_output;
- }
- if (retval = krb5_cc_store_cred(kcontext, ccache, &save_v5creds)) {
- syslog(LOG_ERR,
- "%s while re-storing V5 credentials as user",
- error_message(retval));
-
- }
- skip_ccache_output: krb5_free_cred_contents(kcontext, &save_v5creds);
+ if (got_v5_tickets) {
+ /* set up credential cache -- obeying KRB5_ENV_CCNAME
+ set earlier */
+ /* (KRB5_ENV_CCNAME == "KRB5CCNAME" via osconf.h) */
+ if (retval = krb5_cc_default(kcontext, &ccache)) {
+ com_err(argv[0], retval, "while getting default ccache");
+ } else if (retval = krb5_cc_initialize(kcontext, ccache, me)) {
+ com_err(argv[0], retval, "when initializing cache");
+ } else if (retval = krb5_cc_store_cred(kcontext, ccache, &my_creds)) {
+ com_err(argv[0], retval, "while storing credentials");
+ } else if (xtra_creds &&
+ (retval = krb5_cc_copy_creds(kcontext, xtra_creds,
+ ccache))) {
+ com_err(argv[0], retval, "while storing credentials");
}
+
+ krb5_cc_destroy(kcontext, xtra_creds);
+ } else if (forwarded_v5_tickets && rewrite_ccache) {
+ if ((retval = krb5_cc_initialize (kcontext, ccache, me))) {
+ syslog(LOG_ERR,
+ "%s while re-initializing V5 ccache as user",
+ error_message(retval));
+ } else if (retval = krb5_cc_store_cred(kcontext, ccache,
+ &save_v5creds)) {
+ syslog(LOG_ERR,
+ "%s while re-storing V5 credentials as user",
+ error_message(retval));
+
+ }
+ krb5_free_cred_contents(kcontext, &save_v5creds);
+ }
#endif /* KRB5_GET_TICKETS */
+
#ifdef KRB4_GET_TICKETS
- if (got_v4_tickets&&rewrite_ccache) {
- retval = in_tkt(save_v4creds.pname, save_v4creds.pinst);
- if (retval != KSUCCESS) {
- syslog(LOG_ERR,
- "%s while re-initializing V4 ticket cache as user",
- error_message((retval == -1)?errno:retval));
- goto skip_output_tkfile;
- }
- retval = krb_save_credentials(save_v4creds.service,
- save_v4creds.instance,
- save_v4creds.realm,
- save_v4creds.session,
- save_v4creds.lifetime,
- save_v4creds.kvno,
- &(save_v4creds.ticket_st),
- save_v4creds.issue_date);
- if (retval != KSUCCESS) {
- syslog(LOG_ERR,
- "%s while re-storing V4 tickets as user",
- error_message(retval));
-
- }
+ if (got_v4_tickets && rewrite_ccache) {
+ if ((retval = in_tkt(save_v4creds.pname, save_v4creds.pinst))
+ != KSUCCESS) {
+ syslog(LOG_ERR,
+ "%s while re-initializing V4 ticket cache as user",
+ error_message((retval == -1)?errno:retval));
+ } else if ((retval = krb_save_credentials(save_v4creds.service,
+ save_v4creds.instance,
+ save_v4creds.realm,
+ save_v4creds.session,
+ save_v4creds.lifetime,
+ save_v4creds.kvno,
+ &(save_v4creds.ticket_st),
+ save_v4creds.issue_date))
+ != KSUCCESS) {
+ syslog(LOG_ERR,
+ "%s while re-storing V4 tickets as user",
+ error_message(retval));
}
+ }
#endif /* KRB4_GET_TICKETS */
- skip_output_tkfile: /*null*/;
+ if (*pwd->pw_shell == '\0')
+ pwd->pw_shell = BSHELL;
- if (*pwd->pw_shell == '\0')
- pwd->pw_shell = BSHELL;
#if defined(NTTYDISC) && defined(TIOCSETD)
- /* turn on new line discipline for all shells */
- ioctlval = NTTYDISC;
- (void)ioctl(0, TIOCSETD, (char *)&ioctlval);
+ /* turn on new line discipline for all shells */
+ ioctlval = NTTYDISC;
+ (void)ioctl(0, TIOCSETD, (char *)&ioctlval);
#endif
- ccname = getenv("KRB5CCNAME"); /* save cache */
- tz = getenv("TZ"); /* and time zone */
+ ccname = getenv("KRB5CCNAME"); /* save cache */
+ tz = getenv("TZ"); /* and time zone */
- /* destroy environment unless user has requested preservation */
- if (!pflag) {
- envinit = (char **)malloc(MAXENVIRON * sizeof(char *));
- if (envinit == 0) {
- fprintf(stderr, "Can't malloc empty environment.\n");
- sleepexit(1);
- }
- envinit[0] = NULL;
- environ = envinit;
+ /* destroy environment unless user has requested preservation */
+ if (!pflag) {
+ envinit = (char **) malloc(MAXENVIRON * sizeof(char *));
+ if (envinit == 0) {
+ fprintf(stderr, "Can't malloc empty environment.\n");
+ sleepexit(1);
}
+ envinit[0] = NULL;
+ environ = envinit;
+ }
- setenv ("LOGNAME", pwd->pw_name, 1);
- setenv ("LOGIN", pwd->pw_name, 1);
+ setenv ("LOGNAME", pwd->pw_name, 1);
+ setenv ("LOGIN", pwd->pw_name, 1);
- /* read the /etc/environment file on AIX */
+ /* read the /etc/environment file on AIX */
#ifdef HAVE_ETC_ENVIRONMENT
- read_env_vars_from_file ("/etc/environment");
+ read_env_vars_from_file ("/etc/environment");
#endif
- /* Set login timezone for date information (sgi PDG) */
+ /* Set login timezone for date information (sgi PDG) */
#ifdef HAVE_ETC_TIMEZONE
- read_env_vars_from_file ("/etc/TIMEZONE");
+ read_env_vars_from_file ("/etc/TIMEZONE");
#else
- if (tz)
- setenv ("TZ", tz, 1);
+ if (tz)
+ setenv ("TZ", tz, 1);
#endif
- if (ccname)
- setenv("KRB5CCNAME", ccname, 1);
+ if (ccname)
+ setenv("KRB5CCNAME", ccname, 1);
- setenv("HOME", pwd->pw_dir, 1);
- setenv("PATH", LPATH, 1);
- setenv("USER", pwd->pw_name, 1);
- setenv("SHELL", pwd->pw_shell, 1);
+ setenv("HOME", pwd->pw_dir, 1);
+ setenv("PATH", LPATH, 1);
+ setenv("USER", pwd->pw_name, 1);
+ setenv("SHELL", pwd->pw_shell, 1);
+
+ if (term[0] == '\0') {
+ (void) strncpy(term, stypeof(tty), sizeof(term));
+ term[sizeof(term) - 1] = '\0';
+ }
+ if (term[0])
+ (void)setenv("TERM", term, 0);
- if (term[0] == '\0') {
- (void) strncpy(term, stypeof(tty), sizeof(term));
- term[sizeof(term) - 1] = '\0';
- }
- if (term[0])
- (void)setenv("TERM", term, 0);
#ifdef KRB4_GET_TICKETS
- /* tkfile[0] is only set if we got tickets above */
- if (login_krb4_get_tickets && tkfile[0])
- (void) setenv(KRB_ENVIRON, tkfile, 1);
+ /* tkfile[0] is only set if we got tickets above */
+ if (login_krb4_get_tickets && tkfile[0])
+ (void) setenv(KRB_ENVIRON, tkfile, 1);
#endif /* KRB4_GET_TICKETS */
+
#ifdef KRB5_GET_TICKETS
- /* ccfile[0] is only set if we got tickets above */
- if (login_krb5_get_tickets && ccfile[0])
- (void) setenv(KRB5_ENV_CCNAME, ccfile, 1);
+ /* ccfile[0] is only set if we got tickets above */
+ if (login_krb5_get_tickets && ccfile[0])
+ (void) setenv(KRB5_ENV_CCNAME, ccfile, 1);
#endif /* KRB5_GET_TICKETS */
- if (tty[sizeof("tty")-1] == 'd')
- syslog(LOG_INFO, "DIALUP %s, %s", tty, pwd->pw_name);
- if (pwd->pw_uid == 0)
- if (hostname)
+ if (tty[sizeof("tty")-1] == 'd')
+ syslog(LOG_INFO, "DIALUP %s, %s", tty, pwd->pw_name);
+ if (pwd->pw_uid == 0)
#ifdef KRB4_KLOGIN
- if (kdata) {
- /* @*$&@#*($)#@$ syslog doesn't handle very
- many arguments */
- char buf[BUFSIZ];
+ if (kdata) {
+ if (hostname) {
+ char buf[BUFSIZ];
#ifdef UT_HOSTSIZE
- (void) sprintf(buf,
- "ROOT LOGIN (krb) %s from %.*s, %s.%s@%s",
- tty, UT_HOSTSIZE, hostname,
- kdata->pname, kdata->pinst,
- kdata->prealm);
+ (void) sprintf(buf,
+ "ROOT LOGIN (krb) %s from %.*s, %s.%s@%s",
+ tty, UT_HOSTSIZE, hostname,
+ kdata->pname, kdata->pinst,
+ kdata->prealm);
#else
- (void) sprintf(buf,
- "ROOT LOGIN (krb) %s from %s, %s.%s@%s",
- tty, hostname,
- kdata->pname, kdata->pinst,
- kdata->prealm);
-#endif
- syslog(LOG_NOTICE, "%s", buf);
- } else {
+ (void) sprintf(buf,
+ "ROOT LOGIN (krb) %s from %s, %s.%s@%s",
+ tty, hostname,
+ kdata->pname, kdata->pinst,
+ kdata->prealm);
+#endif
+ syslog(LOG_NOTICE, "%s", buf);
+ } else {
+ syslog(LOG_NOTICE,
+ "ROOT LOGIN (krb) %s, %s.%s@%s",
+ tty,
+ kdata->pname, kdata->pinst,
+ kdata->prealm);
+ }
+ } else
#endif /* KRB4_KLOGIN */
+ {
+ if (hostname) {
#ifdef UT_HOSTSIZE
- syslog(LOG_NOTICE, "ROOT LOGIN %s FROM %.*s",
- tty, UT_HOSTSIZE, hostname);
+ syslog(LOG_NOTICE, "ROOT LOGIN %s FROM %.*s",
+ tty, UT_HOSTSIZE, hostname);
#else
- syslog(LOG_NOTICE, "ROOT LOGIN %s FROM %s",
- tty, hostname);
+ syslog(LOG_NOTICE, "ROOT LOGIN %s FROM %s",
+ tty, hostname);
#endif
-#ifdef KRB4_KLOGIN
- }
- else
- if (kdata) {
- syslog(LOG_NOTICE,
- "ROOT LOGIN (krb) %s, %s.%s@%s",
- tty,
- kdata->pname, kdata->pinst,
- kdata->prealm);
- }
-#endif /* KRB4_KLOGIN */
- else
- syslog(LOG_NOTICE, "ROOT LOGIN %s", tty);
+ } else {
+ syslog(LOG_NOTICE, "ROOT LOGIN %s", tty);
+ }
+ }
- afs_login ();
+ afs_login();
- if (!quietlog) {
+ if (!quietlog) {
#ifdef KRB4_KLOGIN
- if (!krbflag && !fflag && !eflag )
- printf("\nWarning: No Kerberos tickets obtained.\n\n");
+ if (!krbflag && !fflag && !eflag )
+ printf("\nWarning: No Kerberos tickets obtained.\n\n");
#endif /* KRB4_KLOGIN */
- motd ();
- check_mail ();
- }
+ motd();
+ check_mail();
+ }
#ifndef OQUOTA
- if (! access( QUOTAWARN, X_OK)) (void) system(QUOTAWARN);
-#endif
- handler_init (sa, SIG_DFL);
- handler_set (SIGALRM, sa);
- handler_set (SIGQUIT, sa);
- handler_set (SIGINT, sa);
- handler_init (sa, SIG_IGN);
- handler_set (SIGTSTP, sa);
-
- tbuf[0] = '-';
- (void) strncpy(tbuf + 1, (p = strrchr(pwd->pw_shell, '/')) ?
- p + 1 : pwd->pw_shell, sizeof(tbuf) - 1);
- tbuf[sizeof(tbuf) - 1] = '\0';
- execlp(pwd->pw_shell, tbuf, 0);
- fprintf(stderr, "login: no shell: ");
- perror(pwd->pw_shell);
- exit(0);
+ if (! access( QUOTAWARN, X_OK))
+ (void) system(QUOTAWARN);
+#endif
+
+ handler_init (sa, SIG_DFL);
+ handler_set (SIGALRM, sa);
+ handler_set (SIGQUIT, sa);
+ handler_set (SIGINT, sa);
+ handler_init (sa, SIG_IGN);
+ handler_set (SIGTSTP, sa);
+
+ tbuf[0] = '-';
+ p = strrchr(pwd->pw_shell, '/');
+ (void) strncpy(tbuf+1, p?(p+1):pwd->pw_shell, sizeof(tbuf-1));
+ tbuf[sizeof(tbuf) - 1] = '\0';
+
+ execlp(pwd->pw_shell, tbuf, 0);
+ fprintf(stderr, "login: no shell: ");
+ perror(pwd->pw_shell);
+ exit(0);
}
char *speeds[] = {
@@ -1991,212 +1845,216 @@ speed_t b_speeds[] = {
term_init (do_rlogin)
{
- int line_speed = -1;
+ int line_speed = -1;
- if (do_rlogin) {
- register char *cp = strchr(term, '/'), **cpp;
- char *speed;
+ if (do_rlogin) {
+ register char *cp = strchr(term, '/'), **cpp;
+ char *speed;
- if (cp) {
+ if (cp) {
+ *cp++ = '\0';
+ speed = cp;
+ cp = strchr(speed, '/');
+ if (cp)
*cp++ = '\0';
- speed = cp;
- cp = strchr(speed, '/');
- if (cp)
- *cp++ = '\0';
- for (cpp = speeds; cpp < &speeds[NSPEEDS]; cpp++)
- if (strcmp(*cpp, speed) == 0) {
- line_speed = cpp-speeds;
- break;
- }
- }
+ for (cpp = speeds; cpp < &speeds[NSPEEDS]; cpp++)
+ if (strcmp(*cpp, speed) == 0) {
+ line_speed = cpp-speeds;
+ break;
+ }
}
+ }
#ifdef POSIX_TERMIOS
- {
- struct termios tc;
+ {
+ struct termios tc;
- (void)tcgetattr(0, &tc);
- if (line_speed != -1) {
- cfsetispeed(&tc, b_speeds[line_speed]);
- cfsetospeed(&tc, b_speeds[line_speed]);
- }
- tc.c_cc[VMIN] = 1;
- tc.c_cc[VTIME] = 0;
+ (void)tcgetattr(0, &tc);
+ if (line_speed != -1) {
+ cfsetispeed(&tc, b_speeds[line_speed]);
+ cfsetospeed(&tc, b_speeds[line_speed]);
+ }
+ tc.c_cc[VMIN] = 1;
+ tc.c_cc[VTIME] = 0;
#ifndef NO_INIT_CC
- tc.c_cc[VERASE] = CERASE;
- tc.c_cc[VKILL] = CKILL;
- tc.c_cc[VEOF] = CEOF;
- tc.c_cc[VINTR] = CINTR;
- tc.c_cc[VQUIT] = CQUIT;
- tc.c_cc[VSTART] = CSTART;
- tc.c_cc[VSTOP] = CSTOP;
+ tc.c_cc[VERASE] = CERASE;
+ tc.c_cc[VKILL] = CKILL;
+ tc.c_cc[VEOF] = CEOF;
+ tc.c_cc[VINTR] = CINTR;
+ tc.c_cc[VQUIT] = CQUIT;
+ tc.c_cc[VSTART] = CSTART;
+ tc.c_cc[VSTOP] = CSTOP;
#ifndef CNUL
#define CNUL CEOL
#endif
- tc.c_cc[VEOL] = CNUL;
- /* The following are common extensions to POSIX */
+ tc.c_cc[VEOL] = CNUL;
+ /* The following are common extensions to POSIX */
#ifdef VEOL2
- tc.c_cc[VEOL2] = CNUL;
+ tc.c_cc[VEOL2] = CNUL;
#endif
#ifdef VSUSP
#if !defined(CSUSP) && defined(CSWTCH)
#define CSUSP CSWTCH
#endif
- tc.c_cc[VSUSP] = CSUSP;
+ tc.c_cc[VSUSP] = CSUSP;
#endif
#ifdef VDSUSP
- tc.c_cc[VDSUSP] = CDSUSP;
+ tc.c_cc[VDSUSP] = CDSUSP;
#endif
#ifdef VLNEXT
- tc.c_cc[VLNEXT] = CLNEXT;
+ tc.c_cc[VLNEXT] = CLNEXT;
#endif
#ifdef VREPRINT
- tc.c_cc[VREPRINT] = CRPRNT;
+ tc.c_cc[VREPRINT] = CRPRNT;
#endif
#ifdef VDISCRD
- tc.c_cc[VDISCRD] = CFLUSH;
+ tc.c_cc[VDISCRD] = CFLUSH;
#endif
#ifdef VDISCARD
#ifndef CDISCARD
#define CDISCARD CFLUSH
#endif
- tc.c_cc[VDISCARD] = CDISCARD;
+ tc.c_cc[VDISCARD] = CDISCARD;
#endif
#ifdef VWERSE
- tc.c_cc[VWERSE] = CWERASE;
+ tc.c_cc[VWERSE] = CWERASE;
#endif
#ifdef VWERASE
- tc.c_cc[VWERASE] = CWERASE;
+ tc.c_cc[VWERASE] = CWERASE;
#endif
#if defined (VSTATUS) && defined (CSTATUS)
- tc.c_cc[VSTATUS] = CSTATUS;
+ tc.c_cc[VSTATUS] = CSTATUS;
#endif /* VSTATUS && CSTATUS */
#endif /* NO_INIT_CC */
- /* set all standard echo, edit, and job control options */
- /* but leave any extensions */
- tc.c_lflag |= ECHO|ECHOE|ECHOK|ICANON|ISIG|IEXTEN;
- tc.c_lflag &= ~(NOFLSH|TOSTOP);
+ /* set all standard echo, edit, and job control options */
+ /* but leave any extensions */
+ tc.c_lflag |= ECHO|ECHOE|ECHOK|ICANON|ISIG|IEXTEN;
+ tc.c_lflag &= ~(NOFLSH|TOSTOP);
#ifdef ECHOCTL
- /* Not POSIX, but if we have it, we probably want it */
- tc.c_lflag |= ECHOCTL;
+ /* Not POSIX, but if we have it, we probably want it */
+ tc.c_lflag |= ECHOCTL;
#endif
#ifdef ECHOKE
- /* Not POSIX, but if we have it, we probably want it */
- tc.c_lflag |= ECHOKE;
+ /* Not POSIX, but if we have it, we probably want it */
+ tc.c_lflag |= ECHOKE;
#endif
- tc.c_iflag |= ICRNL|BRKINT;
- tc.c_oflag |= ONLCR|OPOST|TAB3;
- tcsetattr(0, TCSANOW, &tc);
- }
+ tc.c_iflag |= ICRNL|BRKINT;
+ tc.c_oflag |= ONLCR|OPOST|TAB3;
+ tcsetattr(0, TCSANOW, &tc);
+ }
#else /* not POSIX_TERMIOS */
- {
- struct sgttyb sgttyb;
- static struct tchars tc = {
- CINTR, CQUIT, CSTART, CSTOP, CEOT, CBRK
- };
- static struct ltchars ltc = {
- CSUSP, CDSUSP, CRPRNT, CFLUSH, CWERASE, CLNEXT
- };
-
- (void) ioctl(0, TIOCGETP, (char *)&sgttyb);
- if (line_speed != -1)
- sgttyb.sg_ispeed = sgttyb.sg_ospeed = line_speed;
- sgttyb.sg_flags = ECHO|CRMOD|ANYP|XTABS;
- sgttyb.sg_erase = CERASE;
- sgttyb.sg_kill = CKILL;
- (void)ioctl(0, TIOCSLTC, (char *)&ltc);
- (void)ioctl(0, TIOCSETC, (char *)&tc);
- (void)ioctl(0, TIOCSETP, (char *)&sgttyb);
+ {
+ struct sgttyb sgttyb;
+ static struct tchars tc = {
+ CINTR, CQUIT, CSTART, CSTOP, CEOT, CBRK
+ };
+ static struct ltchars ltc = {
+ CSUSP, CDSUSP, CRPRNT, CFLUSH, CWERASE, CLNEXT
+ };
+
+ (void) ioctl(0, TIOCGETP, (char *)&sgttyb);
+ if (line_speed != -1)
+ sgttyb.sg_ispeed = sgttyb.sg_ospeed = line_speed;
+ sgttyb.sg_flags = ECHO|CRMOD|ANYP|XTABS;
+ sgttyb.sg_erase = CERASE;
+ sgttyb.sg_kill = CKILL;
+ (void)ioctl(0, TIOCSLTC, (char *)&ltc);
+ (void)ioctl(0, TIOCSETC, (char *)&tc);
+ (void)ioctl(0, TIOCSETP, (char *)&sgttyb);
#if defined(TIOCSETD)
- {
- int ioctlval;
- ioctlval = 0;
- (void)ioctl(0, TIOCSETD, (char *)&ioctlval);
- }
-#endif
+ {
+ int ioctlval;
+ ioctlval = 0;
+ (void)ioctl(0, TIOCSETD, (char *)&ioctlval);
}
#endif
+ }
+#endif
}
void getloginname()
{
- register int ch;
- register char *p;
- static char nbuf[UT_NAMESIZE + 1];
-
- for (;;) {
- printf("login: ");
- for (p = nbuf; (ch = getchar()) != '\n'; ) {
- if (ch == EOF)
- exit(0);
- if (p < nbuf + UT_NAMESIZE)
- *p++ = ch;
- }
- if (p > nbuf)
- if (nbuf[0] == '-')
- fprintf(stderr,
- "login names may not start with '-'.\n");
- else {
- *p = '\0';
- username = nbuf;
- break;
- }
+ register int ch;
+ register char *p;
+ static char nbuf[UT_NAMESIZE + 1];
+
+ for (;;) {
+ printf("login: ");
+ for (p = nbuf; (ch = getchar()) != '\n'; ) {
+ if (ch == EOF)
+ exit(0);
+ if (p < nbuf + UT_NAMESIZE)
+ *p++ = ch;
}
+ if (p > nbuf)
+ if (nbuf[0] == '-')
+ fprintf(stderr,
+ "login names may not start with '-'.\n");
+ else {
+ *p = '\0';
+ username = nbuf;
+ break;
+ }
+ }
}
sigtype
timedout()
{
- fprintf(stderr, "Login timed out after %d seconds\n", timeout);
- exit(0);
+ fprintf(stderr, "Login timed out after %d seconds\n", timeout);
+ exit(0);
}
#ifndef HAVE_TTYENT_H
int root_tty_security = 1;
#endif
+
int rootterm(tty)
char *tty;
{
#ifndef HAVE_TTYENT_H
- return(root_tty_security);
+ return(root_tty_security);
#else
- struct ttyent *t;
+ struct ttyent *t;
- return((t = getttynam(tty)) && t->ty_status&TTY_SECURE);
+ return((t = getttynam(tty)) && t->ty_status&TTY_SECURE);
#endif /* HAVE_TTYENT_H */
}
#ifndef NO_MOTD
sigjmp_buf motdinterrupt;
+
sigtype
sigint()
{
- siglongjmp(motdinterrupt, 1);
+ siglongjmp(motdinterrupt, 1);
}
void motd()
{
- register int fd, nchars;
- char tbuf[8192];
- handler sa, osa;
-
- if ((fd = open(MOTDFILE, O_RDONLY, 0)) < 0)
- return;
- handler_init (sa, sigint);
- handler_swap (SIGINT, sa, osa);
- if (sigsetjmp(motdinterrupt, 1) == 0)
- while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0)
- (void)write(fileno(stdout), tbuf, nchars);
- handler_set (SIGINT, osa);
- (void)close(fd);
+ register int fd, nchars;
+ char tbuf[8192];
+ handler sa, osa;
+
+ if ((fd = open(MOTDFILE, O_RDONLY, 0)) < 0)
+ return;
+ handler_init (sa, sigint);
+ handler_swap (SIGINT, sa, osa);
+ if (sigsetjmp(motdinterrupt, 1) == 0)
+ while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0)
+ (void)write(fileno(stdout), tbuf, nchars);
+ handler_set (SIGINT, osa);
+ (void)close(fd);
}
#else
-void motd () { }
+void motd()
+{
+}
#endif
#ifndef NO_MAILCHECK
-void check_mail ()
+void check_mail()
{
char tbuf[MAXPATHLEN+2];
struct stat st;
@@ -2206,56 +2064,61 @@ void check_mail ()
(st.st_mtime > st.st_atime) ? "new " : "");
}
#else
-void check_mail () { }
+void check_mail()
+{
+}
#endif
void checknologin()
{
- register int fd, nchars;
- char tbuf[8192];
+ register int fd, nchars;
+ char tbuf[8192];
- if ((fd = open(NOLOGIN, O_RDONLY, 0)) >= 0) {
- while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0)
- (void)write(fileno(stdout), tbuf, nchars);
- sleepexit(0);
- }
+ if ((fd = open(NOLOGIN, O_RDONLY, 0)) >= 0) {
+ while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0)
+ (void)write(fileno(stdout), tbuf, nchars);
+ sleepexit(0);
+ }
}
void dolastlog(quiet, tty)
- int quiet;
- char *tty;
+ int quiet;
+ char *tty;
{
#if defined(HAVE_LASTLOG_H) || (defined(BSD) && (BSD >= 199103))
- struct lastlog ll;
- int fd;
+ struct lastlog ll;
+ int fd;
- if ((fd = open(LASTLOG, O_RDWR, 0)) >= 0) {
- (void)lseek(fd, (off_t)pwd->pw_uid * sizeof(ll), SEEK_SET);
- if (!quiet) {
- if (read(fd, (char *)&ll, sizeof(ll)) == sizeof(ll) &&
- ll.ll_time != 0) {
- printf("Last login: %.*s ",
- 24-5, (char *)ctime(&ll.ll_time));
- if (*ll.ll_host != '\0')
- printf("from %.*s\n",
- sizeof(ll.ll_host), ll.ll_host);
- else
- printf("on %.*s\n",
- sizeof(ll.ll_line), ll.ll_line);
- }
- (void)lseek(fd, (off_t)pwd->pw_uid * sizeof(ll), SEEK_SET);
- }
- (void)time(&ll.ll_time);
- (void) strncpy(ll.ll_line, tty, sizeof(ll.ll_line));
- ll.ll_line[sizeof(ll.ll_line) - 1] = '\0';
- if (hostname) {
- (void) strncpy(ll.ll_host, hostname, sizeof(ll.ll_host));
- ll.ll_host[sizeof(ll.ll_host) - 1] = '\0';
- } else
- (void) memset(ll.ll_host, 0, sizeof(ll.ll_host));
- (void)write(fd, (char *)&ll, sizeof(ll));
- (void)close(fd);
+ if ((fd = open(LASTLOG, O_RDWR, 0)) >= 0) {
+ (void)lseek(fd, (off_t)pwd->pw_uid * sizeof(ll), SEEK_SET);
+ if (!quiet) {
+ if ((read(fd, (char *)&ll, sizeof(ll)) == sizeof(ll)) &&
+ (ll.ll_time != 0)) {
+
+ printf("Last login: %.*s ", 24-5, (char *)ctime(&ll.ll_time));
+
+ if (*ll.ll_host != '\0')
+ printf("from %.*s\n", sizeof(ll.ll_host), ll.ll_host);
+ else
+ printf("on %.*s\n", sizeof(ll.ll_line), ll.ll_line);
+ }
+ (void)lseek(fd, (off_t)pwd->pw_uid * sizeof(ll), SEEK_SET);
+ }
+ (void) time(&ll.ll_time);
+
+ (void) strncpy(ll.ll_line, tty, sizeof(ll.ll_line));
+ ll.ll_line[sizeof(ll.ll_line) - 1] = '\0';
+
+ if (hostname) {
+ (void) strncpy(ll.ll_host, hostname, sizeof(ll.ll_host));
+ ll.ll_host[sizeof(ll.ll_host) - 1] = '\0';
+ } else {
+ (void) memset(ll.ll_host, 0, sizeof(ll.ll_host));
}
+
+ (void)write(fd, (char *)&ll, sizeof(ll));
+ (void)close(fd);
+ }
#endif
}
@@ -2268,166 +2131,168 @@ void dolastlog(quiet, tty)
char *
stypeof(ttyid)
- char *ttyid;
+ char *ttyid;
{
-char *cp = getenv("term");
+ char *cp = getenv("term");
#ifndef HAVE_TTYENT_H
-if (cp)
- return cp;
-else return(UNKNOWN);
+ if (cp)
+ return cp;
+ else
+ return(UNKNOWN);
#else
- struct ttyent *t;
- if (cp)
- return cp;
- else return(ttyid && (t = getttynam(ttyid)) ? t->ty_type : UNKNOWN);
+ struct ttyent *t;
+ if (cp)
+ return cp;
+ else
+ return(ttyid && (t = getttynam(ttyid)) ? t->ty_type : UNKNOWN);
#endif
}
int doremotelogin(host)
- char *host;
+ char *host;
{
- static char lusername[UT_NAMESIZE+1];
- char rusername[UT_NAMESIZE+1];
-
- lgetstr(rusername, sizeof(rusername), "Remote user");
- lgetstr(lusername, sizeof(lusername), "Local user");
- lgetstr(term, sizeof(term), "Terminal type");
- username = lusername;
- pwd = getpwnam(username);
- if (pwd == NULL)
- return(-1);
- return(ruserok(host, (pwd->pw_uid == 0), rusername, username));
+ static char lusername[UT_NAMESIZE+1];
+ char rusername[UT_NAMESIZE+1];
+
+ lgetstr(rusername, sizeof(rusername), "Remote user");
+ lgetstr(lusername, sizeof(lusername), "Local user");
+ lgetstr(term, sizeof(term), "Terminal type");
+ username = lusername;
+ pwd = getpwnam(username);
+ if (pwd == NULL)
+ return(-1);
+ return(ruserok(host, (pwd->pw_uid == 0), rusername, username));
}
#ifdef KRB4_KLOGIN
int do_krb_login(host, strict)
- char *host;
- int strict;
+ char *host;
+ int strict;
{
- int rc;
- struct sockaddr_in sin;
- char instance[INST_SZ], version[9];
- long authoptions = 0L;
- struct hostent *hp = gethostbyname(host);
- static char lusername[UT_NAMESIZE+1];
+ int rc;
+ struct sockaddr_in sin;
+ char instance[INST_SZ], version[9];
+ long authoptions = 0L;
+ struct hostent *hp = gethostbyname(host);
+ static char lusername[UT_NAMESIZE+1];
+
+ /*
+ * Kerberos autologin protocol.
+ */
+ (void) memset((char *) &sin, 0, (int) sizeof(sin));
+
+ if (hp)
+ (void) memcpy ((char *)&sin.sin_addr, hp->h_addr,
+ sizeof(sin.sin_addr));
+ else
+ sin.sin_addr.s_addr = inet_addr(host);
+
+ if ((hp == NULL) && (sin.sin_addr.s_addr == -1)) {
+ printf("Hostname did not resolve to an address, so Kerberos authentication failed\r\n");
/*
- * Kerberos autologin protocol.
+ * No host addr prevents auth, so
+ * punt krb and require password
*/
-
- (void) memset((char *) &sin, 0, (int) sizeof(sin));
-
- if (hp)
- (void) memcpy ((char *)&sin.sin_addr, hp->h_addr,
- sizeof(sin.sin_addr));
- else
- sin.sin_addr.s_addr = inet_addr(host);
-
- if ((hp == NULL) && (sin.sin_addr.s_addr == -1)) {
- printf("Hostname did not resolve to an address, so Kerberos authentication failed\r\n");
- /*
- * No host addr prevents auth, so
- * punt krb and require password
- */
- if (strict) {
- goto paranoid;
- } else {
- pwd = NULL;
- return(-1);
- }
+ if (strict) {
+ goto paranoid;
+ } else {
+ pwd = NULL;
+ return(-1);
}
+ }
- kdata = (AUTH_DAT *)malloc( sizeof(AUTH_DAT) );
- ticket = (KTEXT) malloc(sizeof(KTEXT_ST));
+ kdata = (AUTH_DAT *)malloc( sizeof(AUTH_DAT) );
+ ticket = (KTEXT) malloc(sizeof(KTEXT_ST));
- (void) strcpy(instance, "*");
- if ((rc=krb_recvauth(authoptions, 0, ticket, "rcmd",
- instance, &sin,
- (struct sockaddr_in *)0,
- kdata, "", (bit_64 *) 0, version))) {
- printf("Kerberos rlogin failed: %s\r\n",krb_get_err_text(rc));
- if (strict) {
+ (void) strcpy(instance, "*");
+ if ((rc=krb_recvauth(authoptions, 0, ticket, "rcmd",
+ instance, &sin,
+ (struct sockaddr_in *)0,
+ kdata, "", (bit_64 *) 0, version))) {
+ printf("Kerberos rlogin failed: %s\r\n",krb_get_err_text(rc));
+ if (strict) {
paranoid:
- /*
- * Paranoid hosts, such as a Kerberos server,
- * specify the Klogind daemon to disallow
- * even password access here.
- */
- printf("Sorry, you must have Kerberos authentication to access this host.\r\n");
- exit(1);
- }
- }
- (void) lgetstr(lusername, sizeof (lusername), "Local user");
- (void) lgetstr(term, sizeof(term), "Terminal type");
- username = lusername;
- if (getuid()) {
- pwd = NULL;
- return(-1);
- }
- pwd = getpwnam(lusername);
- if (pwd == NULL) {
- pwd = NULL;
- return(-1);
+ /*
+ * Paranoid hosts, such as a Kerberos server,
+ * specify the Klogind daemon to disallow
+ * even password access here.
+ */
+ printf("Sorry, you must have Kerberos authentication to access this host.\r\n");
+ exit(1);
}
+ }
+ (void) lgetstr(lusername, sizeof (lusername), "Local user");
+ (void) lgetstr(term, sizeof(term), "Terminal type");
+ username = lusername;
+ if (getuid()) {
+ pwd = NULL;
+ return(-1);
+ }
+ pwd = getpwnam(lusername);
+ if (pwd == NULL) {
+ pwd = NULL;
+ return(-1);
+ }
- /*
- * if Kerberos login failed because of an error in krb_recvauth,
- * return the indication of a bad attempt. User will be prompted
- * for a password. We CAN'T check the .rhost file, because we need
- * the remote username to do that, and the remote username is in the
- * Kerberos ticket. This affects ONLY the case where there is
- * Kerberos on both ends, but Kerberos fails on the server end.
- */
- if (rc) {
- return(-1);
- }
+ /*
+ * if Kerberos login failed because of an error in krb_recvauth,
+ * return the indication of a bad attempt. User will be prompted
+ * for a password. We CAN'T check the .rhost file, because we need
+ * the remote username to do that, and the remote username is in the
+ * Kerberos ticket. This affects ONLY the case where there is
+ * Kerberos on both ends, but Kerberos fails on the server end.
+ */
+ if (rc) {
+ return(-1);
+ }
- if ((rc=kuserok(kdata,lusername))) {
- printf("login: %s has not given you permission to login without a password.\r\n",lusername);
- if (strict) {
- exit(1);
- }
- return(-1);
+ if ((rc=kuserok(kdata,lusername))) {
+ printf("login: %s has not given you permission to login without a password.\r\n",lusername);
+ if (strict) {
+ exit(1);
}
- return(0);
+ return(-1);
+ }
+ return(0);
}
#endif /* KRB4_KLOGIN */
void lgetstr(buf, cnt, err)
- char *buf, *err;
- int cnt;
+ char *buf, *err;
+ int cnt;
{
- int ocnt = cnt;
- char *obuf = buf;
- char ch;
-
- do {
- if (read(0, &ch, sizeof(ch)) != sizeof(ch))
- exit(1);
- if (--cnt < 0) {
- fprintf(stderr,"%s '%.*s' too long, %d characters maximum.\r\n",
- err, ocnt, obuf, ocnt-1);
- sleepexit(1);
- }
- *buf++ = ch;
- } while (ch);
+ int ocnt = cnt;
+ char *obuf = buf;
+ char ch;
+
+ do {
+ if (read(0, &ch, sizeof(ch)) != sizeof(ch))
+ exit(1);
+ if (--cnt < 0) {
+ fprintf(stderr,"%s '%.*s' too long, %d characters maximum.\r\n",
+ err, ocnt, obuf, ocnt-1);
+ sleepexit(1);
+ }
+ *buf++ = ch;
+ } while (ch);
}
void sleepexit(eval)
- int eval;
+ int eval;
{
#ifdef KRB4_GET_TICKETS
- if (login_krb4_get_tickets && krbflag)
- (void) destroy_tickets();
+ if (login_krb4_get_tickets && krbflag)
+ (void) destroy_tickets();
#endif /* KRB4_GET_TICKETS */
- sleep((u_int)5);
- exit(eval);
+ sleep((u_int)5);
+ exit(eval);
}
#if defined(KRB4_GET_TICKETS) || defined(KRB5_GET_TICKETS)
-
static int hungup = 0;
+
static sigtype
sighup() {
hungup = 1;
@@ -2448,34 +2313,38 @@ dofork()
#ifdef _IBMR2
update_ref_count(1);
#endif
- if(!(child=fork()))
- return; /* Child process returns */
+ if (!(child=fork()))
+ return; /* Child process returns */
/* The parent continues here */
- { /* Try and get rid of our controlling tty. On SunOS, this may or may
- not work depending on if our parent did a setsid before exec-ing us. */
+ /* Try and get rid of our controlling tty. On SunOS, this may or may
+ not work depending on if our parent did a setsid before exec-ing
+ us. */
#ifndef __linux__
- /* On linux, TIOCNOTTY causes us to die on a
- SIGHUP, so don't even try it. */
+ /* On linux, TIOCNOTTY causes us to die on a
+ SIGHUP, so don't even try it. */
#ifdef TIOCNOTTY
- { int fd;
- if ((fd = open("/dev/tty", O_RDWR)) >= 0) {
- ioctl(fd, TIOCNOTTY, 0);
- close(fd);
- }
- }
+ {
+ int fd;
+
+ if ((fd = open("/dev/tty", O_RDWR)) >= 0) {
+ ioctl(fd, TIOCNOTTY, 0);
+ close(fd);
+ }
+ }
#endif
#endif /* __linux__ */
+
#ifdef HAVE_SETSID
- (void)setsid();
+ (void)setsid();
#endif
+
#ifdef SETPGRP_TWOARG
- (void)setpgrp(0, 0);
+ (void)setpgrp(0, 0);
#else
- (void)setpgrp();
+ (void)setpgrp();
#endif
- }
/* Setup stuff? This would be things we could do in parallel with login */
(void) chdir("/"); /* Let's not keep the fs busy... */
@@ -2489,21 +2358,22 @@ dofork()
while (1) {
#ifdef HAVE_WAITPID
pid = waitpid(child, 0, 0);
-#else
-#ifdef WAIT_USES_INT
+#elif defined(WAIT_USES_INT)
pid = wait((int *)0);
#else
pid = wait((union wait *)0);
#endif
-#endif
- if (hungup)
+
+ if (hungup) {
#ifdef HAVE_KILLPG
killpg(child, SIGHUP);
#else
kill(-child, SIGHUP);
#endif
+ }
+
if (pid == child)
- break;
+ break;
}
/* Cleanup stuff */
@@ -2525,20 +2395,18 @@ dofork()
for compatablilty with version 5 krb library, since kcmd.o is linked
into all programs. */
-char *
- strsave(sp)
-char *sp;
+char *strsave(sp)
+ char *sp;
{
register char *ret;
- if((ret = (char *) malloc((unsigned) strlen(sp)+1)) == NULL) {
+ if ((ret = (char *) malloc((unsigned) strlen(sp)+1)) == NULL) {
fprintf(stderr, "no memory for saving args\n");
exit(1);
}
(void) strcpy(ret,sp);
return(ret);
}
-
#endif
#ifdef _IBMR2
diff --git a/src/appl/gss-sample/ChangeLog b/src/appl/gss-sample/ChangeLog
index 476fb5bce..bdf6e8d71 100644
--- a/src/appl/gss-sample/ChangeLog
+++ b/src/appl/gss-sample/ChangeLog
@@ -1,3 +1,15 @@
+1998-10-24 Marc Horowitz <marc@mit.edu>
+
+ * gss-server.c (sign_server): fix the text heuristic to recognize
+ whitespace as text.
+ (main): clean up file descriptors properly after each
+ connection.
+
+ * gss-client.c (read_file): properly handle empty files
+
+ * gss-client.c: (call_server): NUL-terminate the contents
+ of non-empty files on the wire.
+
Wed Feb 18 15:27:32 1998 Tom Yu <tlyu@mit.edu>
* Makefile.in: Remove trailing slash from BUILDTOP. Fix up
diff --git a/src/appl/gss-sample/gss-client.c b/src/appl/gss-sample/gss-client.c
index e0bca99c4..33a7e963a 100644
--- a/src/appl/gss-sample/gss-client.c
+++ b/src/appl/gss-sample/gss-client.c
@@ -239,25 +239,29 @@ void read_file(file_name, in_buf)
exit(1);
}
in_buf->length = stat_buf.st_size;
- in_buf->value = malloc(in_buf->length);
- if (in_buf->value == 0) {
+
+ if (in_buf->length == 0) {
+ in_buf->value = NULL;
+ return;
+ }
+
+ if ((in_buf->value = malloc(in_buf->length)) == 0) {
fprintf(stderr, "Couldn't allocate %d byte buffer for reading file\n",
in_buf->length);
exit(1);
}
- memset(in_buf->value, 0, in_buf->length);
- for (bytes_in = 0; bytes_in < in_buf->length; bytes_in += count) {
- count = read(fd, in_buf->value, in_buf->length);
- if (count < 0) {
- perror("read");
- exit(1);
- }
- if (count == 0)
- break;
+
+ /* this code used to check for incomplete reads, but you can't get
+ an incomplete read on any file for which fstat() is meaningful */
+
+ count = read(fd, in_buf->value, in_buf->length);
+ if (count < 0) {
+ perror("read");
+ exit(1);
}
- if (bytes_in != count)
+ if (count < in_buf->length)
fprintf(stderr, "Warning, only read in %d bytes, expected %d\n",
- bytes_in, count);
+ count, in_buf->length);
}
/*
@@ -281,8 +285,7 @@ void read_file(file_name, in_buf)
* seals msg in a GSS-API token with gss_seal, sends it to the server,
* reads back a GSS-API signature block for msg from the server, and
* verifies it with gss_verify. -1 is returned if any step fails,
- * otherwise 0 is returned.
- */
+ * otherwise 0 is returned. */
int call_server(host, port, oid, service_name, deleg_flag, msg, use_file)
char *host;
u_short port;
@@ -410,7 +413,7 @@ int call_server(host, port, oid, service_name, deleg_flag, msg, use_file)
} else {
/* Seal the message */
in_buf.value = msg;
- in_buf.length = strlen(msg) + 1;
+ in_buf.length = strlen(msg);
}
maj_stat = gss_wrap(&min_stat, context, 1, GSS_C_QOP_DEFAULT,
diff --git a/src/appl/gss-sample/gss-server.c b/src/appl/gss-sample/gss-server.c
index ef9d49582..3e9ff0959 100644
--- a/src/appl/gss-sample/gss-server.c
+++ b/src/appl/gss-sample/gss-server.c
@@ -393,9 +393,10 @@ int sign_server(s, server_creds)
fprintf(log, "Received message: ");
cp = msg_buf.value;
- if (isprint(cp[0]) && isprint(cp[1]))
- fprintf(log, "\"%s\"\n", cp);
- else {
+ if ((isprint(cp[0]) || isspace(cp[0])) &&
+ (isprint(cp[1]) || isspace(cp[1]))) {
+ fprintf(log, "\"%.*s\"\n", msg_buf.length, msg_buf.value);
+ } else {
printf("\n");
print_token(&msg_buf);
}
@@ -488,20 +489,21 @@ main(argc, argv)
} else {
int stmp;
- if ((stmp = create_socket(port))) {
+ if ((stmp = create_socket(port)) >= 0) {
do {
/* Accept a TCP connection */
if ((s = accept(stmp, NULL, 0)) < 0) {
perror("accepting connection");
- } else {
- /* this return value is not checked, because there's
- not really anything to do if it fails */
- sign_server(s, server_creds);
+ continue;
}
+ /* this return value is not checked, because there's
+ not really anything to do if it fails */
+ sign_server(s, server_creds);
+ close(s);
} while (!once);
- }
- close(stmp);
+ close(stmp);
+ }
}
(void) gss_release_cred(&min_stat, &server_creds);
diff --git a/src/appl/gssftp/ftp/ChangeLog b/src/appl/gssftp/ftp/ChangeLog
index ed4aecb1a..b021129b0 100644
--- a/src/appl/gssftp/ftp/ChangeLog
+++ b/src/appl/gssftp/ftp/ChangeLog
@@ -1,3 +1,10 @@
+1998-10-26 Marc Horowitz <marc@mit.edu>
+
+ * ftp.c (login): *always* encrypt the password, regardless
+ of the default command mode.
+ (do_auth): Try the new krb5 mech, and if that fails, try the
+ old one.
+
1998-10-26 Geoffrey King <gjking@mit.edu>
* ftp.M: Add documentation for new ccc and cprotect commands.
diff --git a/src/appl/gssftp/ftp/ftp.c b/src/appl/gssftp/ftp/ftp.c
index f6fb15677..d19d62c20 100644
--- a/src/appl/gssftp/ftp/ftp.c
+++ b/src/appl/gssftp/ftp/ftp.c
@@ -31,6 +31,32 @@
* SUCH DAMAGE.
*/
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ *
+ * 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 FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. FundsXpress makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
#ifndef lint
static char sccsid[] = "@(#)ftp.c 5.38 (Berkeley) 4/22/91";
#endif /* not lint */
@@ -95,11 +121,13 @@ MSG_DAT msg_data;
#endif /* KRB5_KRB4_COMPAT */
#ifdef GSSAPI
#include <gssapi/gssapi.h>
-#include <gssapi/gssapi_generic.h>
+/* need to include the krb5 file, because we're doing manual fallback
+ from the v2 mech to the v2 mech. Once there's real negotiation,
+ we can be generic again. */
+#include <gssapi/gssapi_krb5.h>
gss_ctx_id_t gcontext;
#endif /* GSSAPI */
-
static int kerror; /* XXX needed for all auth types */
char *auth_type; /* Authentication succeeded? If so, what type? */
@@ -308,7 +336,8 @@ login(host)
if (pass == NULL)
pass = mygetpass("Password:");
#ifndef NOENCRYPTION
- if ((oldclevel = clevel) == PROT_S) clevel = PROT_P;
+ oldclevel = clevel;
+ clevel = PROT_P;
#endif
n = command("PASS %s", pass);
#ifndef NOENCRYPTION
@@ -1843,8 +1872,16 @@ char realm[REALM_SZ + 1];
#endif /* KRB5_KRB4_COMPAT */
#ifdef GSSAPI
-/* for testing, we don't have an ftp key yet */
-char* gss_services[] = { "ftp", "host", 0 };
+struct {
+ const gss_OID_desc * const * mech_type;
+ char *service_name;
+} gss_trials[] = {
+ { &gss_mech_krb5_v2, "ftp" },
+ { &gss_mech_krb5, "ftp" },
+ { &gss_mech_krb5_v2, "host" },
+ { &gss_mech_krb5, "host" },
+};
+int n_gss_trials = sizeof(gss_trials)/sizeof(gss_trials[0]);
#endif /* GSSAPI */
do_auth()
@@ -1870,8 +1907,7 @@ do_auth()
gss_name_t target_name;
gss_buffer_desc send_tok, recv_tok, *token_ptr;
char stbuf[FTP_BUFSIZ];
- char **service_name, **end_service_name;
- int comcode;
+ int comcode, trial;
struct gss_channel_bindings_struct chan;
chan.initiator_addrtype = GSS_C_AF_INET; /* OM_uint32 */
chan.initiator_address.length = 4;
@@ -1882,21 +1918,15 @@ do_auth()
chan.application_data.length = 0;
chan.application_data.value = 0;
- for (end_service_name = gss_services; *end_service_name; )
- end_service_name++;
- end_service_name--;
-
if (verbose)
- printf("%s accepted as authentication type\n", "GSSAPI");
+ printf("GSSAPI accepted as authentication type\n");
/* blob from gss-client */
-
- for (service_name = gss_services; *service_name; service_name++) {
-
+ for (trial = 0; trial < n_gss_trials; trial++) {
/* ftp@hostname first, the host@hostname */
/* the V5 GSSAPI binding canonicalizes this for us... */
- sprintf(stbuf, "%s@%s", *service_name, hostname);
+ sprintf(stbuf, "%s@%s", gss_trials[trial].service_name, hostname);
if (debug)
fprintf(stderr, "Trying to authenticate to <%s>\n", stbuf);
@@ -1922,7 +1952,7 @@ do_auth()
GSS_C_NO_CREDENTIAL,
&gcontext,
target_name,
- GSS_C_NULL_OID,
+ *gss_trials[trial].mech_type,
GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG |
(forward ? GSS_C_DELEG_FLAG : 0),
0,
@@ -1935,7 +1965,7 @@ do_auth()
if (maj_stat!=GSS_S_COMPLETE && maj_stat!=GSS_S_CONTINUE_NEEDED){
- if (service_name == end_service_name)
+ if (trial == n_gss_trials-1)
user_gss_error(maj_stat, min_stat, "initializing context");
(void) gss_release_name(&min_stat, &target_name);
/* could just be that we missed on the service name */
@@ -1946,16 +1976,28 @@ do_auth()
int len = send_tok.length;
reply_parse = "ADAT="; /* for command() later */
oldverbose = verbose;
- verbose = 0;
+ verbose = (trial == n_gss_trials-1)?0:-1;
kerror = radix_encode(send_tok.value, out_buf, &len, 0);
if (kerror) {
fprintf(stderr, "Base 64 encoding failed: %s\n",
radix_error(kerror));
} else if ((comcode = command("ADAT %s", out_buf))!=COMPLETE
/* && comcode != 3 (335)*/) {
- fprintf(stderr, "GSSAPI ADAT failed\n");
- /* force out of loop */
- maj_stat = GSS_S_FAILURE;
+ if (trial == n_gss_trials-1) {
+ fprintf(stderr, "GSSAPI ADAT failed\n");
+ /* force out of loop */
+ maj_stat = GSS_S_FAILURE;
+ }
+ /* backoff to the v1 gssapi is still possible. Send
+ a new AUTH command. If that fails, terminate the
+ loop */
+ if (command("AUTH %s", "GSSAPI") != CONTINUE) {
+ fprintf(stderr,
+ "GSSAPI ADAT failed, AUTH restart failed\n");
+ /* force out of loop */
+ maj_stat = GSS_S_FAILURE;
+ }
+ goto outer_loop;
} else if (!reply_parse) {
fprintf(stderr,
"No authentication data received from server\n");
@@ -1979,7 +2021,7 @@ do_auth()
/* get out of loop clean */
gss_complete_loop:
- service_name = end_service_name;
+ trial = n_gss_trials-1;
gss_release_buffer(&min_stat, &send_tok);
gss_release_name(&min_stat, &target_name);
goto outer_loop;
@@ -1991,8 +2033,7 @@ do_auth()
}
verbose = oldverbose;
if (maj_stat == GSS_S_COMPLETE) {
- if (verbose)
- printf("GSSAPI authentication succeeded\n");
+ printf("GSSAPI authentication succeeded\n");
reply_parse = NULL;
auth_type = "GSSAPI";
return(1);
diff --git a/src/appl/telnet/libtelnet/ChangeLog b/src/appl/telnet/libtelnet/ChangeLog
index 494050438..55168c36b 100644
--- a/src/appl/telnet/libtelnet/ChangeLog
+++ b/src/appl/telnet/libtelnet/ChangeLog
@@ -1,3 +1,10 @@
+1998-10-26 Marc Horowitz <marc@mit.edu>
+
+ * enc_des.c, kerberos.c: the ECB des functions don't exist
+ anymore, but telnet always encrypted/decrypted one block. Convert
+ to calls to the new crypto api, with des-cbc-raw, using a single
+ block.
+
Tue Mar 3 14:43:30 1998 Theodore Ts'o <tytso@rsts-11.mit.edu>
* configure.in: Change test for cgetent to use HAVE_ instead
diff --git a/src/appl/telnet/libtelnet/enc_des.c b/src/appl/telnet/libtelnet/enc_des.c
index f44700a73..3912b35e9 100644
--- a/src/appl/telnet/libtelnet/enc_des.c
+++ b/src/appl/telnet/libtelnet/enc_des.c
@@ -31,11 +31,38 @@
* SUCH DAMAGE.
*/
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ *
+ * 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 FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. FundsXpress makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
/* based on @(#)enc_des.c 8.1 (Berkeley) 6/4/93 */
#ifdef ENCRYPTION
# ifdef AUTHENTICATION
# ifdef DES_ENCRYPTION
+#include <krb5.h>
#include <arpa/telnet.h>
#include <stdio.h>
#ifdef __STDC__
@@ -53,6 +80,8 @@
extern encrypt_debug_mode;
+extern krb5_context telnet_context;
+
#define CFB 0
#define OFB 1
@@ -65,20 +94,19 @@ extern encrypt_debug_mode;
struct fb {
- Block krbdes_key;
- Schedule krbdes_sched;
Block temp_feed;
unsigned char fb_feed[64];
int need_start;
int state[2];
int keyid[2];
int once;
+ int validkey;
struct stinfo {
Block str_output;
Block str_feed;
Block str_iv;
- Block str_ikey;
- Schedule str_sched;
+ unsigned char str_keybytes[8]; /* yuck */
+ krb5_keyblock str_key;
int str_index;
int str_flagshift;
} streams[2];
@@ -122,6 +150,29 @@ static void fb64_session P((Session_Key *, int, struct fb *));
void fb64_stream_key P((Block, struct stinfo *));
int fb64_keyid P((int, unsigned char *, int *, struct fb *));
+static void ecb_encrypt(stp, in, out)
+ struct stinfo *stp;
+ Block in;
+ Block out;
+{
+ krb5_error_code code;
+ krb5_data din;
+ krb5_enc_data dout;
+
+ din.length = 8;
+ din.data = in;
+
+ dout.ciphertext.length = 8;
+ dout.ciphertext.data = out;
+ dout.enctype = ENCTYPE_UNKNOWN;
+
+ code = krb5_c_encrypt(telnet_context, &stp->str_key, 0, 0,
+ &din, &dout);
+ /* XXX I'm not sure what to do if this fails */
+ if (code)
+ com_err("libtelnet", code, "encrypting stream data");
+}
+
void
cfb64_init(server)
int server;
@@ -207,7 +258,7 @@ fb64_start(fbp, dir, server)
else if ((state & NO_SEND_IV) == 0)
break;
- if (!VALIDKEY(fbp->krbdes_key)) {
+ if (!fbp->validkey) {
fbp->need_start = 1;
break;
}
@@ -218,9 +269,18 @@ fb64_start(fbp, dir, server)
/*
* Create a random feed and send it over.
*/
- des_new_random_key(fbp->temp_feed);
- des_ecb_encrypt(fbp->temp_feed, fbp->temp_feed,
- fbp->krbdes_sched, 1);
+ {
+ krb5_data d;
+ krb5_error_code code;
+
+ d.data = fbp->temp_feed;
+ d.length = sizeof(fbp->temp_feed);
+
+ if (code = krb5_c_random_make_octets(telnet_context,
+ &d))
+ return(FAILED);
+ }
+
p = fbp->fb_feed + 3;
*p++ = ENCRYPT_IS;
p++;
@@ -418,23 +478,18 @@ fb64_session(key, server, fbp)
int server;
struct fb *fbp;
{
-
if (!key || key->type != SK_DES) {
if (encrypt_debug_mode)
printf("Can't set krbdes's session key (%d != %d)\r\n",
key ? key->type : -1, SK_DES);
return;
}
- memcpy((void *)fbp->krbdes_key, (void *)key->data, sizeof(Block));
- fb64_stream_key(fbp->krbdes_key, &fbp->streams[DIR_ENCRYPT-1]);
- fb64_stream_key(fbp->krbdes_key, &fbp->streams[DIR_DECRYPT-1]);
+ fbp->validkey = 1;
+
+ fb64_stream_key(key->data, &fbp->streams[DIR_ENCRYPT-1]);
+ fb64_stream_key(key->data, &fbp->streams[DIR_DECRYPT-1]);
- if (fbp->once == 0) {
- des_set_random_generator_seed(fbp->krbdes_key);
- fbp->once = 1;
- }
- des_key_sched(fbp->krbdes_key, fbp->krbdes_sched);
/*
* Now look to see if krbdes_start() was was waiting for
* the key to show up. If so, go ahead an call it now
@@ -551,12 +606,9 @@ fb64_stream_iv(seed, stp)
Block seed;
register struct stinfo *stp;
{
-
memcpy((void *)stp->str_iv, (void *)seed, sizeof(Block));
memcpy((void *)stp->str_output, (void *)seed, sizeof(Block));
- des_key_sched(stp->str_ikey, stp->str_sched);
-
stp->str_index = sizeof(Block);
}
@@ -565,8 +617,13 @@ fb64_stream_key(key, stp)
Block key;
register struct stinfo *stp;
{
- memcpy((void *)stp->str_ikey, (void *)key, sizeof(Block));
- des_key_sched(key, stp->str_sched);
+ memcpy((void *)stp->str_keybytes, (void *)key, sizeof(Block));
+ stp->str_key.length = 8;
+ stp->str_key.contents = stp->str_keybytes;
+ /* the original version of this code uses des ecb mode, but
+ it only ever does one block at a time. cbc with a zero iv
+ is identical */
+ stp->str_key.enctype = ENCTYPE_DES_CBC_RAW;
memcpy((void *)stp->str_output, (void *)stp->str_iv, sizeof(Block));
@@ -607,7 +664,7 @@ cfb64_encrypt(s, c)
while (c-- > 0) {
if (index == sizeof(Block)) {
Block b;
- des_ecb_encrypt(stp->str_output, b, stp->str_sched, 1);
+ ecb_encrypt(stp, stp->str_output, b);
memcpy((void *)stp->str_feed,(void *)b,sizeof(Block));
index = 0;
}
@@ -641,7 +698,7 @@ cfb64_decrypt(data)
index = stp->str_index++;
if (index == sizeof(Block)) {
Block b;
- des_ecb_encrypt(stp->str_output, b, stp->str_sched, 1);
+ ecb_encrypt(stp, stp->str_output, b);
memcpy((void *)stp->str_feed, (void *)b, sizeof(Block));
stp->str_index = 1; /* Next time will be 1 */
index = 0; /* But now use 0 */
@@ -683,7 +740,7 @@ ofb64_encrypt(s, c)
while (c-- > 0) {
if (index == sizeof(Block)) {
Block b;
- des_ecb_encrypt(stp->str_feed, b, stp->str_sched, 1);
+ ecb_encrypt(stp, stp->str_feed, b);
memcpy((void *)stp->str_feed,(void *)b,sizeof(Block));
index = 0;
}
@@ -714,7 +771,7 @@ ofb64_decrypt(data)
index = stp->str_index++;
if (index == sizeof(Block)) {
Block b;
- des_ecb_encrypt(stp->str_feed, b, stp->str_sched, 1);
+ ecb_encrypt(stp, stp->str_feed, b);
memcpy((void *)stp->str_feed, (void *)b, sizeof(Block));
stp->str_index = 1; /* Next time will be 1 */
index = 0; /* But now use 0 */
diff --git a/src/appl/telnet/libtelnet/kerberos.c b/src/appl/telnet/libtelnet/kerberos.c
index 63738b53b..ed32392c9 100644
--- a/src/appl/telnet/libtelnet/kerberos.c
+++ b/src/appl/telnet/libtelnet/kerberos.c
@@ -53,7 +53,38 @@
* or implied warranty.
*/
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ *
+ * 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 FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. FundsXpress makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
#ifdef KRB4
+/* this code must be compiled in the krb5 tree. disgustingly, there
+ is code in here which declares structures which happen to mirror
+ the krb4 des structures. I didn't want to rototill this *completely*
+ so this is how it's going to work. --marc */
+#include <krb5.h>
#include <sys/types.h>
#include <arpa/telnet.h>
#include <stdio.h>
@@ -73,6 +104,7 @@
#include "misc.h"
extern auth_debug_mode;
+extern krb5_context telnet_context;
static unsigned char str_data[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 0,
AUTHTYPE_KERBEROS_V4, };
@@ -93,6 +125,7 @@ static AUTH_DAT adat = { 0 };
#ifdef ENCRYPTION
static Block session_key = { 0 };
static Schedule sched;
+static krb5_keyblock krbkey;
static Block challenge = { 0 };
#endif /* ENCRYPTION */
@@ -146,6 +179,9 @@ kerberos4_init(ap, server)
} else {
str_data[3] = TELQUAL_IS;
}
+
+ kerberos5_init(NULL, server);
+
return(1);
}
@@ -157,15 +193,18 @@ kerberos4_send(ap)
Authenticator *ap;
{
KTEXT_ST auth;
-#ifdef ENCRYPTION
- Block enckey;
-#endif /* ENCRYPTION */
char instance[INST_SZ];
char *realm;
char *krb_realmofhost();
char *krb_get_phost();
CREDENTIALS cred;
int r;
+#ifdef ENCRYPTION
+ krb5_data data;
+ krb5_enc_data encdata;
+ krb5_error_code code;
+ krb5_keyblock random_key;
+#endif
printf("[ Trying KERBEROS4 ... ]\r\n");
if (!UserNameRequested) {
@@ -216,11 +255,56 @@ kerberos4_send(ap)
if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
register int i;
- des_key_sched(cred.session, sched);
- des_init_random_number_generator(cred.session);
- des_new_random_key(session_key);
- des_ecb_encrypt(session_key, session_key, sched, 0);
- des_ecb_encrypt(session_key, challenge, sched, 0);
+ data.data = cred.session;
+ data.length = 8; /* sizeof(cred.session) */;
+
+ if (code = krb5_c_random_seed(telnet_context, &data)) {
+ com_err("libtelnet", code,
+ "while seeding random number generator");
+ return(0);
+ }
+
+ if (code = krb5_c_make_random_key(telnet_context,
+ ENCTYPE_DES_CBC_RAW,
+ &random_key)) {
+ com_err("libtelnet", code,
+ "while creating random session key");
+ return(0);
+ }
+
+ /* the krb4 code uses ecb mode, but on a single block
+ with a zero ivec, ecb and cbc are the same */
+ krbkey.enctype = ENCTYPE_DES_CBC_RAW;
+ krbkey.length = 8;
+ krbkey.contents = cred.session;
+
+ encdata.ciphertext.data = random_key.contents;
+ encdata.ciphertext.length = random_key.length;
+ encdata.enctype = ENCTYPE_UNKNOWN;
+
+ data.data = session_key;
+ data.length = 8;
+
+ code = krb5_c_decrypt(telnet_context, &krbkey, 0, 0,
+ &encdata, &data);
+
+ krb5_free_keyblock_contents(telnet_context, &random_key);
+
+ if (code) {
+ com_err("libtelnet", code, "while encrypting random key");
+ return(0);
+ }
+
+ encdata.ciphertext.data = session_key;
+ encdata.ciphertext.length = 8;
+ encdata.enctype = ENCTYPE_UNKNOWN;
+
+ data.data = challenge;
+ data.length = 8;
+
+ code = krb5_c_decrypt(telnet_context, &krbkey, 0, 0,
+ &encdata, &data);
+
/*
* Increment the challenge by 1, and encrypt it for
* later comparison.
@@ -232,7 +316,19 @@ kerberos4_send(ap)
if (x < 256) /* if no overflow, all done */
break;
}
- des_ecb_encrypt(challenge, challenge, sched, 1);
+
+ data.data = challenge;
+ data.length = 8;
+
+ encdata.ciphertext.data = challenge;
+ encdata.ciphertext.length = 8;
+ encdata.enctype = ENCTYPE_UNKNOWN;
+
+ if (code = krb5_c_encrypt(telnet_context, &krbkey, 0, 0, &data,
+ &encdata)) {
+ com_err("libtelnet", code, "while encrypting random key");
+ return(0);
+ }
}
#endif /* ENCRYPTION */
@@ -253,7 +349,10 @@ kerberos4_is(ap, data, cnt)
{
#ifdef ENCRYPTION
Session_Key skey;
- Block datablock;
+ Block datablock, tmpkey;
+ krb5_data kdata;
+ krb5_enc_data encdata;
+ krb5_error_code code;
#endif /* ENCRYPTION */
char realm[REALM_SZ];
char instance[INST_SZ];
@@ -317,24 +416,60 @@ kerberos4_is(ap, data, cnt)
* Initialize the random number generator since it's
* used later on by the encryption routine.
*/
- des_init_random_number_generator(session_key);
- des_key_sched(session_key, sched);
+
+ kdata.data = session_key;
+ kdata.length = 8;
+
+ if (code = krb5_c_random_seed(telnet_context, &kdata)) {
+ com_err("libtelnet", code,
+ "while seeding random number generator");
+ return;
+ }
+
memcpy((void *)datablock, (void *)data, sizeof(Block));
/*
* Take the received encrypted challenge, and encrypt
* it again to get a unique session_key for the
* ENCRYPT option.
*/
- des_ecb_encrypt(datablock, session_key, sched, 1);
+ krbkey.enctype = ENCTYPE_DES_CBC_RAW;
+ krbkey.length = 8;
+ krbkey.contents = session_key;
+
+ kdata.data = datablock;
+ kdata.length = 8;
+
+ encdata.ciphertext.data = tmpkey;
+ encdata.ciphertext.length = 8;
+ encdata.enctype = ENCTYPE_UNKNOWN;
+
+ if (code = krb5_c_encrypt(telnet_context, &krbkey, 0, 0,
+ &kdata, &encdata)) {
+ com_err("libtelnet", code, "while encrypting random key");
+ return;
+ }
+
skey.type = SK_DES;
skey.length = 8;
- skey.data = session_key;
+ skey.data = tmpkey;
encrypt_session_key(&skey, 1);
/*
* Now decrypt the received encrypted challenge,
* increment by one, re-encrypt it and send it back.
*/
- des_ecb_encrypt(datablock, challenge, sched, 0);
+ encdata.ciphertext.data = datablock;
+ encdata.ciphertext.length = 8;
+ encdata.enctype = ENCTYPE_UNKNOWN;
+
+ kdata.data = challenge;
+ kdata.length = 8;
+
+ if (code = krb5_c_decrypt(telnet_context, &krbkey, 0, 0,
+ &encdata, &kdata)) {
+ com_err("libtelnet", code, "while decrypting challenge");
+ return;
+ }
+
for (r = 7; r >= 0; r--) {
register int t;
t = (unsigned int)challenge[r] + 1;
@@ -342,7 +477,20 @@ kerberos4_is(ap, data, cnt)
if (t < 256) /* if no overflow, all done */
break;
}
- des_ecb_encrypt(challenge, challenge, sched, 1);
+
+ kdata.data = challenge;
+ kdata.length = 8;
+
+ encdata.ciphertext.data = challenge;
+ encdata.ciphertext.length = 8;
+ encdata.enctype = ENCTYPE_UNKNOWN;
+
+ if (code = krb5_c_encrypt(telnet_context, &krbkey, 0, 0,
+ &kdata, &encdata)) {
+ com_err("libtelnet", code, "while decrypting challenge");
+ return;
+ }
+
Data(ap, KRB_RESPONSE, (void *)challenge, sizeof(challenge));
#endif /* ENCRYPTION */
break;
@@ -363,6 +511,10 @@ kerberos4_reply(ap, data, cnt)
{
#ifdef ENCRYPTION
Session_Key skey;
+ krb5_data kdata;
+ krb5_enc_data encdata;
+ krb5_error_code code;
+
#endif /* ENCRYPTION */
if (cnt-- < 1)
@@ -387,7 +539,21 @@ kerberos4_reply(ap, data, cnt)
#else /* ENCRYPTION */
Data(ap, KRB_CHALLENGE, (void *)session_key,
sizeof(session_key));
- des_ecb_encrypt(session_key, session_key, sched, 1);
+
+ kdata.data = session_key;
+ kdata.length = 8;
+
+ encdata.ciphertext.data = session_key;
+ encdata.ciphertext.length = 8;
+ encdata.enctype = ENCTYPE_UNKNOWN;
+
+ if (code = krb5_c_encrypt(telnet_context, &krbkey,
+ 0, 0, &kdata, &encdata)) {
+ com_err("libtelnet", code,
+ "while encrypting session_key");
+ return;
+ }
+
skey.type = SK_DES;
skey.length = 8;
skey.data = session_key;
diff --git a/src/appl/telnet/telnet/ChangeLog b/src/appl/telnet/telnet/ChangeLog
index 6d13e63f2..7d94d0acf 100644
--- a/src/appl/telnet/telnet/ChangeLog
+++ b/src/appl/telnet/telnet/ChangeLog
@@ -1,3 +1,10 @@
+1998-10-26 Marc Horowitz <marc@mit.edu>
+
+ * commands.c: remove calls to setuid(getuid()). This looks like
+ it was once an attempt to make it safe to run setuid, but it's not
+ safe for a number of other reasons, so there's no reason to
+ pretend.
+
Sat Oct 10 06:24:55 1998 Geoffrey King <gjking@mit.edu>
* telnet.c (telnet): Cosmetic change: Put a newline after "Waiting
diff --git a/src/appl/telnet/telnet/commands.c b/src/appl/telnet/telnet/commands.c
index 5c8ae3cb7..c23e199cc 100644
--- a/src/appl/telnet/telnet/commands.c
+++ b/src/appl/telnet/telnet/commands.c
@@ -2378,7 +2378,6 @@ tn(argc, argv)
if (connected) {
printf("?Already connected to %s\r\n", hostname);
- setuid(getuid());
return 0;
}
if (argc < 2) {
@@ -2419,7 +2418,6 @@ tn(argc, argv)
}
usage:
printf("usage: %s [-l user] [-a] host-name [port]\r\n", cmd);
- setuid(getuid());
return 0;
}
if (hostp == 0)
@@ -2434,11 +2432,9 @@ tn(argc, argv)
temp = sourceroute(hostp, &srp, &srlen);
if (temp == 0) {
herror(srp);
- setuid(getuid());
return 0;
} else if (temp == -1) {
printf("Bad source route option: %s\r\n", hostp);
- setuid(getuid());
return 0;
} else {
sin.sin_addr.s_addr = temp;
@@ -2468,7 +2464,6 @@ tn(argc, argv)
hostname = _hostname;
} else {
herror(hostp);
- setuid(getuid());
return 0;
}
}
@@ -2489,7 +2484,6 @@ tn(argc, argv)
sin.sin_port = sp->s_port;
else {
printf("%s: bad port number\r\n", portp);
- setuid(getuid());
return 0;
}
} else {
@@ -2500,7 +2494,6 @@ tn(argc, argv)
sp = getservbyname("telnet", "tcp");
if (sp == 0) {
fprintf(stderr, "telnet: tcp/telnet: unknown service\n");
- setuid(getuid());
return 0;
}
sin.sin_port = sp->s_port;
@@ -2510,7 +2503,6 @@ tn(argc, argv)
printf("Trying %s...\r\n", inet_ntoa(sin.sin_addr));
do {
net = socket(AF_INET, SOCK_STREAM, 0);
- setuid(getuid());
if (net < 0) {
perror("telnet: socket");
return 0;