diff --git a/ChangeLog b/ChangeLog index 02541c81..07caf915 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,47 @@ +2013-04-09 Mats Erik Andersson + + telnet, telnetd: Termcap buffer length recommendation. + + * telnet/telnet.c (termbuf): Increase length to 2048, + and initialize to zero. + (init_term) [HAVE_TGETENT]: Handle case `err == 1', + since it can only happen here. + * telnetd/utility.c (terminaltypeok) [HAVE_TGETENT]: + Declare BUF. Call tgetent() to decide return status. + [!HAVE_GETENT]: Always return 1, lacking the knowledge + to make any other decision relvant for return status. + + telnetd, libtelnet: Buffer overflow prevention. + + * telnetd/telnetd.h (getterminaltype): New signature. + * telnetd/telnetd.c (telnetd_setup): Add buffer + length in call getterminaltype(). + * telnetd/utility.c (getterminaltype): New second + argument `size_t len'. Pass `len' to auth_wait(). + * libtelnet/auth-proto.h (auth_wait): New signature. + (kerberos4_status) [KRB4]: Likewise. + (kerberos5_status) [KRB5]: Likewise. + (krb5shishi_status) [SHISHI]: Likewise. + * libtelnet/auth.h (typedef TN_Authenticator): + New signature of member `*status'. + * libtelnet/auth.c (auth_wait): New parameter `len'. + Pass `len' in the call *authenticated->status(). + * libtelnet/kerberos.c (kerberos4_status): New third + argument `size_t len'. Call strncpy(). + * libtelnet/kerberos5.c (kerberos5_status): Likewise. + * libtelnet/shishi.c (krb5shishi_status): Likewise. + (krb5shishi_is_auth): Type CNAMEREALMLEN as size_t. + + libtelnet: Minor warnings for casts. + + * libtelnet/encrypt.h (typedef Session_Key) + [!HAVE_ARPA_TELNET_H_SESSION_KEY]: Make `data' a + const char pointer. + * libtelnet/encrypt.c (EncryptDisable): Cast second + argument in genget() as `char **'. Cast argument + to Ambiguous() as `char *'. + (EncryptType): Likewise. + 2013-04-05 Mats Erik Andersson talk: Non-ASCII characters. diff --git a/libtelnet/auth-proto.h b/libtelnet/auth-proto.h index 7d213759..975a3951 100644 --- a/libtelnet/auth-proto.h +++ b/libtelnet/auth-proto.h @@ -78,7 +78,7 @@ void auth_send_retry (void); void auth_is (unsigned char *, int); void auth_reply (unsigned char *, int); void auth_finished (TN_Authenticator *, int); -int auth_wait (char *); +int auth_wait (char *, size_t); void auth_name (unsigned char *, int); void auth_disable_name (char *); void auth_printsub (unsigned char *, int, unsigned char *, int); @@ -89,7 +89,7 @@ int kerberos4_init (TN_Authenticator *, int); int kerberos4_send (TN_Authenticator *); void kerberos4_is (TN_Authenticator *, unsigned char *, int); void kerberos4_reply (TN_Authenticator *, unsigned char *, int); -int kerberos4_status (TN_Authenticator *, char *, int); +int kerberos4_status (TN_Authenticator *, char *, size_t, int); void kerberos4_printsub (unsigned char *, int, unsigned char *, int); # endif @@ -98,7 +98,7 @@ int kerberos5_init (TN_Authenticator *, int); int kerberos5_send (TN_Authenticator *); void kerberos5_is (TN_Authenticator *, unsigned char *, int); void kerberos5_reply (TN_Authenticator *, unsigned char *, int); -int kerberos5_status (TN_Authenticator *, char *, int); +int kerberos5_status (TN_Authenticator *, char *, size_t, int); void kerberos5_printsub (unsigned char *, int, unsigned char *, int); # endif @@ -107,7 +107,7 @@ int krb5shishi_init (TN_Authenticator *, int); int krb5shishi_send (TN_Authenticator *); void krb5shishi_is (TN_Authenticator *, unsigned char *, int); void krb5shishi_reply (TN_Authenticator *, unsigned char *, int); -int krb5shishi_status (TN_Authenticator *, char *, int); +int krb5shishi_status (TN_Authenticator *, char *, size_t, int); void krb5shishi_printsub (unsigned char *, int, unsigned char *, int); void krb5shishi_cleanup (TN_Authenticator *); # endif diff --git a/libtelnet/auth.c b/libtelnet/auth.c index 753377d3..9e5a61b8 100644 --- a/libtelnet/auth.c +++ b/libtelnet/auth.c @@ -664,7 +664,7 @@ auth_intr (int sig _GL_UNUSED_PARAMETER) } int -auth_wait (char *name) +auth_wait (char *name, size_t len) { if (auth_debug_mode) printf (">>>%s: in auth_wait.\r\n", Name); @@ -690,7 +690,8 @@ auth_wait (char *name) validuser = AUTH_USER; if (authenticated->status) - validuser = (*authenticated->status) (authenticated, name, validuser); + validuser = (*authenticated->status) (authenticated, name, len, + validuser); return (validuser); } diff --git a/libtelnet/auth.h b/libtelnet/auth.h index 4c8474a4..340acb52 100644 --- a/libtelnet/auth.h +++ b/libtelnet/auth.h @@ -95,7 +95,7 @@ typedef struct XauthP int (*send) (struct XauthP *); void (*is) (struct XauthP *, unsigned char *, int); void (*reply) (struct XauthP *, unsigned char *, int); - int (*status) (struct XauthP *, char *, int); + int (*status) (struct XauthP *, char *, size_t, int); void (*printsub) (unsigned char *, int, unsigned char *, int); void (*cleanup) (struct XauthP *); } TN_Authenticator; diff --git a/libtelnet/encrypt.c b/libtelnet/encrypt.c index f28c2dde..b55aa9b2 100644 --- a/libtelnet/encrypt.c +++ b/libtelnet/encrypt.c @@ -265,10 +265,10 @@ EncryptDisable (char *type, char *mode) printf ("Usage: encrypt disable [input|output]\n"); encrypt_list_types (); } - else if ((ep = (Encryptions *) genget (type, encryptions, + else if ((ep = (Encryptions *) genget (type, (char **) encryptions, sizeof (Encryptions))) == 0) printf ("%s: invalid encryption type\n", type); - else if (Ambiguous (ep)) + else if (Ambiguous ((char *) ep)) printf ("Ambiguous type '%s'\n", type); else { @@ -303,10 +303,10 @@ EncryptType (char *type, char *mode) printf ("Usage: encrypt type [input|output]\n"); encrypt_list_types (); } - else if ((ep = (Encryptions *) genget (type, encryptions, + else if ((ep = (Encryptions *) genget (type, (char **) encryptions, sizeof (Encryptions))) == 0) printf ("%s: invalid encryption type\n", type); - else if (Ambiguous (ep)) + else if (Ambiguous ((char *) ep)) printf ("Ambiguous type '%s'\n", type); else { diff --git a/libtelnet/encrypt.h b/libtelnet/encrypt.h index 2dcdb0a8..444826ff 100644 --- a/libtelnet/encrypt.h +++ b/libtelnet/encrypt.h @@ -96,7 +96,7 @@ typedef struct { Block _; } Schedule[16]; -# endif /* HAVE_ARPA_TELNET_H_SCHEDULE */ +# endif /* !HAVE_ARPA_TELNET_H_SCHEDULE */ # ifndef VALIDKEY # define VALIDKEY(key) ( key[0] | key[1] | key[2] | key[3] | \ @@ -110,9 +110,9 @@ typedef struct { short type; int length; - unsigned char *data; + const unsigned char *data; } Session_Key; -# endif /* HAVE_ARPA_TELNET_H_SESSION_KEY */ +# endif /* !HAVE_ARPA_TELNET_H_SESSION_KEY */ typedef struct { diff --git a/libtelnet/kerberos.c b/libtelnet/kerberos.c index 8d80c5f5..74179c15 100644 --- a/libtelnet/kerberos.c +++ b/libtelnet/kerberos.c @@ -475,9 +475,10 @@ kerberos4_reply (ap, data, cnt) } int -kerberos4_status (ap, name, level) +kerberos4_status (ap, name, len, level) TN_Authenticator *ap; char *name; + size_t len; int level; { if (level < AUTH_USER) @@ -485,7 +486,7 @@ kerberos4_status (ap, name, level) if (UserNameRequested && !kuserok (&adat, UserNameRequested)) { - strcpy (name, UserNameRequested); + strncpy (name, UserNameRequested, len); return (AUTH_VALID); } else diff --git a/libtelnet/kerberos5.c b/libtelnet/kerberos5.c index 7b41ae5e..521def6c 100644 --- a/libtelnet/kerberos5.c +++ b/libtelnet/kerberos5.c @@ -426,7 +426,8 @@ kerberos5_reply (TN_Authenticator * ap, unsigned char *data, int cnt) } int -kerberos5_status (TN_Authenticator * ap, char *name, int level) +kerberos5_status (TN_Authenticator * ap, char *name, size_t len, + int level) { if (level < AUTH_USER) return level; @@ -436,7 +437,7 @@ kerberos5_status (TN_Authenticator * ap, char *name, int level) UserNameRequested)) { /* FIXME: Check buffer length */ - strcpy (name, UserNameRequested); + strncpy (name, UserNameRequested, len); return AUTH_VALID; } return AUTH_USER; diff --git a/libtelnet/shishi.c b/libtelnet/shishi.c index 9edd4e5b..d51ec41a 100644 --- a/libtelnet/shishi.c +++ b/libtelnet/shishi.c @@ -392,7 +392,8 @@ krb5shishi_reply (TN_Authenticator * ap, unsigned char *data, int cnt) } int -krb5shishi_status (TN_Authenticator * ap, char *name, int level) +krb5shishi_status (TN_Authenticator * ap, char *name, size_t len, + int level) { int rc; int status; @@ -406,7 +407,7 @@ krb5shishi_status (TN_Authenticator * ap, char *name, int level) UserNameRequested)) { /* FIXME: Check buffer length */ - strcpy (name, UserNameRequested); + strncpy (name, UserNameRequested, len); status = AUTH_VALID; } else @@ -422,7 +423,7 @@ krb5shishi_is_auth (TN_Authenticator * a, unsigned char *data, int cnt, Shishi_key *key, *key2; int rc; char *cnamerealm, *server = NULL, *realm = NULL; - int cnamerealmlen; + size_t cnamerealmlen; # ifdef ENCRYPTION Session_Key skey; # endif diff --git a/telnet/telnet.c b/telnet/telnet.c index ab1cb99c..8055fc7d 100644 --- a/telnet/telnet.c +++ b/telnet/telnet.c @@ -604,7 +604,7 @@ is_unique (register char *name, register char **as, register char **ae) /* * Given a buffer returned by tgetent(), this routine will turn - * the pipe seperated list of names in the buffer into an array + * the pipe separated list of names in the buffer into an array * of pointers to null terminated names. We toss out any bad, * duplicate, or verbose names (names with spaces). */ @@ -642,7 +642,7 @@ mklist (char *buf, char *name) n++; } /* - * Allocate an array to put the name pointers into + * Allocate an array to put the name pointers into. */ argv = (char **) malloc ((n + 3) * sizeof (char *)); if (argv == 0) @@ -733,16 +733,20 @@ mklist (char *buf, char *name) return (unknown); } - -char termbuf[1024]; +/* Mostly ignored by contemorary implementations, + * but still used by NetBSD. + * mklist will examine this buffer, so erase it + * to cover corner cases. + */ +char termbuf[2048] = { 0 }; static int init_term (char *tname, int *errp) { int err = -1; + #ifdef HAVE_TGETENT err = tgetent (termbuf, tname); -#endif if (err == 1) { termbuf[sizeof (termbuf) - 1] = '\0'; @@ -750,6 +754,7 @@ init_term (char *tname, int *errp) *errp = 1; return (0); } +#endif /* HAVE_TGETENT */ if (errp) *errp = 0; return (-1); diff --git a/telnetd/telnetd.c b/telnetd/telnetd.c index 82243c54..3dfec8dc 100644 --- a/telnetd/telnetd.c +++ b/telnetd/telnetd.c @@ -474,7 +474,7 @@ telnetd_setup (int fd) /* get terminal type. */ uname[0] = 0; - level = getterminaltype (uname); + level = getterminaltype (uname, sizeof (uname)); setenv ("TERM", terminaltype ? terminaltype : "network", 1); if (uname[0]) user_name = xstrdup (uname); diff --git a/telnetd/telnetd.h b/telnetd/telnetd.h index b0baa0a7..64431956 100644 --- a/telnetd/telnetd.h +++ b/telnetd/telnetd.h @@ -369,7 +369,7 @@ extern int (*decrypt_input) (int); #endif /* ENCRYPTION */ extern int startslave (char *host, int autologin, char *autoname); -extern int getterminaltype (char *user_name); +extern int getterminaltype (char *user_name, size_t len); extern int net_input_level (void); extern int net_output_level (void); extern int net_read (void); diff --git a/telnetd/utility.c b/telnetd/utility.c index 3ef79622..4e669b72 100644 --- a/telnetd/utility.c +++ b/telnetd/utility.c @@ -688,11 +688,11 @@ _gettermname (void) ttloop (sequenceIs (ttypesubopt, baseline)); } -/* FIXME: should be getterminaltype (char *user_name, size_t size) - Changes terminaltype. +/* + * Changes terminaltype. */ int -getterminaltype (char *user_name) +getterminaltype (char *user_name, size_t len) { int retval = -1; @@ -718,7 +718,7 @@ getterminaltype (char *user_name) ttloop (his_will_wont_is_changing (TELOPT_AUTHENTICATION)); if (his_state_is_will (TELOPT_AUTHENTICATION)) - retval = auth_wait (user_name); + retval = auth_wait (user_name, len); } #else /* !AUTHENTICATION */ (void) user_name; /* Silence warning. */ @@ -844,18 +844,24 @@ getterminaltype (char *user_name) return retval; } +/* + * Exit status: + * + * 1 Accepted terminal type, or inconclusive, + * 0 Explicitly unsupported type. + */ int terminaltypeok (char *s) { +#ifdef HAVE_TGETENT char buf[2048]; if (terminaltype == NULL) return 1; -#ifdef HAVE_TGETENT if (tgetent (buf, s) == 0) -#endif return 0; +#endif /* HAVE_TGETENT */ return 1; }