From 9ab4f412312f92f6d0c4db702777c9956ce7cfa0 Mon Sep 17 00:00:00 2001 From: Mike Barcroft Date: Sun, 12 Aug 2001 17:54:49 +0000 Subject: o Replace occurrences of strncpy(3) with strlcpy(3); most of the uses of it were wrong anyway. o Always check for NULL returns on strdup(3). o Fix a possible buffer overflow in strcpy(3). o Fix a format string vulnerability. o t->ty_type in stypeof() could be NULL and eventually cause a segmentation fault in setenv(3), so check for that. Eyeballed by: kris Reviewed by: murray MFC after: 3 days --- usr.bin/login/login.c | 70 ++++++++++++++++++++++++++++++++++----------------- 1 file changed, 47 insertions(+), 23 deletions(-) diff --git a/usr.bin/login/login.c b/usr.bin/login/login.c index 3c9f5a188515..b3a25e1f07f7 100644 --- a/usr.bin/login/login.c +++ b/usr.bin/login/login.c @@ -210,7 +210,10 @@ main(argc, argv) if (uid) errx(1, "-h option: %s", strerror(EPERM)); hflag = 1; - strncpy(full_hostname, optarg, sizeof(full_hostname)-1); + if (strlcpy(full_hostname, optarg, + sizeof(full_hostname)) >= sizeof(full_hostname)) + errx(1, "-h option: %s: exceeds maximum " + "hostname size", optarg); trimdomain(optarg, UT_HOSTSIZE); @@ -232,6 +235,11 @@ main(argc, argv) NI_NUMERICHOST| NI_WITHSCOPEID); optarg = strdup(hostbuf); + if (optarg == NULL) { + syslog(LOG_NOTICE, + "strdup(): %m"); + sleepexit(1); + } } else optarg = "invalid hostname"; if (res != NULL) @@ -304,8 +312,7 @@ main(argc, argv) if (failures > (pwd ? 0 : 1)) badlogin(tbuf); } - (void)strncpy(tbuf, username, sizeof tbuf-1); - tbuf[sizeof tbuf-1] = '\0'; + (void)strlcpy(tbuf, username, sizeof(tbuf)); pwd = getpwnam(username); @@ -466,7 +473,10 @@ main(argc, argv) getnameinfo(res->ai_addr, res->ai_addrlen, hostbuf, sizeof(hostbuf), NULL, 0, NI_NUMERICHOST|NI_WITHSCOPEID); - optarg = strdup(hostbuf); + if ((optarg = strdup(hostbuf)) == NULL) { + syslog(LOG_NOTICE, "strdup(): %m"); + sleepexit(1); + } } else optarg = NULL; if (res != NULL) @@ -487,7 +497,7 @@ main(argc, argv) if (*shell == '\0') /* Not overridden */ shell = pwd->pw_shell; if ((shell = strdup(shell)) == NULL) { - syslog(LOG_NOTICE, "memory allocation error"); + syslog(LOG_NOTICE, "strdup(): %m"); sleepexit(1); } @@ -499,10 +509,10 @@ main(argc, argv) /* Nothing else left to fail -- really log in. */ memset((void *)&utmp, 0, sizeof(utmp)); (void)time(&utmp.ut_time); - (void)strncpy(utmp.ut_name, username, sizeof(utmp.ut_name)); + (void)strlcpy(utmp.ut_name, username, sizeof(utmp.ut_name)); if (hostname) - (void)strncpy(utmp.ut_host, hostname, sizeof(utmp.ut_host)); - (void)strncpy(utmp.ut_line, tty, sizeof(utmp.ut_line)); + (void)strlcpy(utmp.ut_host, hostname, sizeof(utmp.ut_host)); + (void)strlcpy(utmp.ut_line, tty, sizeof(utmp.ut_line)); login(&utmp); dolastlog(quietlog); @@ -530,8 +540,13 @@ main(argc, argv) /* * Preserve TERM if it happens to be already set. */ - if ((term = getenv("TERM")) != NULL) - term = strdup(term); + if ((term = getenv("TERM")) != NULL) { + if ((term = strdup(term)) == NULL) { + syslog(LOG_NOTICE, + "strdup(): %m"); + sleepexit(1); + } + } /* * Exclude cons/vt/ptys only, assume dialup otherwise @@ -673,10 +688,9 @@ main(argc, argv) motd(cw); cw = getenv("MAIL"); /* $MAIL may have been set by class */ - if (cw != NULL) { - strncpy(tbuf, cw, sizeof(tbuf)); - tbuf[sizeof(tbuf)-1] = '\0'; - } else + if (cw != NULL) + strlcpy(tbuf, cw, sizeof(tbuf)); + else snprintf(tbuf, sizeof(tbuf), "%s/%s", _PATH_MAILDIR, pwd->pw_name); if (stat(tbuf, &st) == 0 && st.st_size != 0) @@ -699,9 +713,13 @@ main(argc, argv) /* * Login shells have a leading '-' in front of argv[0] */ - tbuf[0] = '-'; - (void)strcpy(tbuf + 1, - (p = strrchr(pwd->pw_shell, '/')) ? p + 1 : pwd->pw_shell); + if (snprintf(tbuf, sizeof(tbuf), "-%s", + (p = strrchr(pwd->pw_shell, '/')) ? p + 1 : pwd->pw_shell) >= + sizeof(tbuf)) { + syslog(LOG_ERR, "user: %s: shell exceeds maximum pathname size", + username); + errx(1, "shell exceeds maximum pathname size"); + } execlp(shell, tbuf, (char *)0); err(1, "%s", shell); @@ -898,7 +916,7 @@ getloginname() static char nbuf[NBUFSIZ]; for (;;) { - (void)printf(prompt); + (void)printf("%s", prompt); for (p = nbuf; (ch = getchar()) != '\n'; ) { if (ch == EOF) { badlogin(username); @@ -931,10 +949,9 @@ rootterm(ttyn) volatile int motdinterrupt; -/* ARGSUSED */ void sigint(signo) - int signo; + int signo __unused; { motdinterrupt = 1; } @@ -994,11 +1011,13 @@ dolastlog(quiet) } memset((void *)&ll, 0, sizeof(ll)); (void)time(&ll.ll_time); - (void)strncpy(ll.ll_line, tty, sizeof(ll.ll_line)); + (void)strlcpy(ll.ll_line, tty, sizeof(ll.ll_line)); if (hostname) - (void)strncpy(ll.ll_host, hostname, sizeof(ll.ll_host)); + (void)strlcpy(ll.ll_host, hostname, sizeof(ll.ll_host)); (void)write(fd, (char *)&ll, sizeof(ll)); (void)close(fd); + } else { + syslog(LOG_ERR, "cannot open %s: %m", _PATH_LASTLOG); } } @@ -1034,7 +1053,12 @@ stypeof(ttyid) { struct ttyent *t; - return (ttyid && (t = getttynam(ttyid)) ? t->ty_type : UNKNOWN); + if (ttyid != NULL && *ttyid != '\0') { + t = getttynam(ttyid); + if (t != NULL && t->ty_type != NULL) + return (t->ty_type); + } + return ("UNKNOWN"); } void -- cgit v1.2.3