diff options
| author | Marc Horowitz <marc@mit.edu> | 1998-10-30 02:56:35 +0000 |
|---|---|---|
| committer | Marc Horowitz <marc@mit.edu> | 1998-10-30 02:56:35 +0000 |
| commit | 1440ab035ba04550ddbbfbff1ee9b5571e3d95db (patch) | |
| tree | 9d5e8d2e151a930e044c7d0f7c64053d244577a0 /src/appl | |
| parent | 61ddbf948ba6ee70c1bc049268c3dfa73bc9983e (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/ChangeLog | 23 | ||||
| -rw-r--r-- | src/appl/bsd/kcmd.c | 125 | ||||
| -rw-r--r-- | src/appl/bsd/krlogin.c | 175 | ||||
| -rw-r--r-- | src/appl/bsd/krlogind.c | 175 | ||||
| -rw-r--r-- | src/appl/bsd/login.c | 2306 | ||||
| -rw-r--r-- | src/appl/gss-sample/ChangeLog | 12 | ||||
| -rw-r--r-- | src/appl/gss-sample/gss-client.c | 35 | ||||
| -rw-r--r-- | src/appl/gss-sample/gss-server.c | 22 | ||||
| -rw-r--r-- | src/appl/gssftp/ftp/ChangeLog | 7 | ||||
| -rw-r--r-- | src/appl/gssftp/ftp/ftp.c | 91 | ||||
| -rw-r--r-- | src/appl/telnet/libtelnet/ChangeLog | 7 | ||||
| -rw-r--r-- | src/appl/telnet/libtelnet/enc_des.c | 109 | ||||
| -rw-r--r-- | src/appl/telnet/libtelnet/kerberos.c | 200 | ||||
| -rw-r--r-- | src/appl/telnet/telnet/ChangeLog | 7 | ||||
| -rw-r--r-- | src/appl/telnet/telnet/commands.c | 8 |
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 *)<c); - (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 *)<c); + (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; |
