summaryrefslogtreecommitdiff
path: root/loginrec.c
diff options
context:
space:
mode:
authorColin Watson <cjwatson@debian.org>2010-01-01 23:53:30 +0000
committerColin Watson <cjwatson@debian.org>2010-01-01 23:53:30 +0000
commitdf03186a4f9e0c2ece398b5c0571cb6263d7a752 (patch)
tree1aab079441dff9615274769b19f2d734ddf508dd /loginrec.c
parent6ad6994c288662fca6949f42bf91fec2aff00bca (diff)
parent99b402ea4c8457b0a3cafff37f5b3410a8dc6476 (diff)
* New upstream release (closes: #536182). Yes, I know 5.3p1 has been out
for a while, but there's no GSSAPI patch available for it yet. - Change the default cipher order to prefer the AES CTR modes and the revised "arcfour256" mode to CBC mode ciphers that are susceptible to CPNI-957037 "Plaintext Recovery Attack Against SSH". - Add countermeasures to mitigate CPNI-957037-style attacks against the SSH protocol's use of CBC-mode ciphers. Upon detection of an invalid packet length or Message Authentication Code, ssh/sshd will continue reading up to the maximum supported packet length rather than immediately terminating the connection. This eliminates most of the known differences in behaviour that leaked information about the plaintext of injected data which formed the basis of this attack (closes: #506115, LP: #379329). - ForceCommand directive now accepts commandline arguments for the internal-sftp server (closes: #524423, LP: #362511). - Add AllowAgentForwarding to available Match keywords list (closes: #540623). - Make ssh(1) send the correct channel number for SSH2_MSG_CHANNEL_SUCCESS and SSH2_MSG_CHANNEL_FAILURE messages to avoid triggering 'Non-public channel' error messages on sshd(8) in openssh-5.1. - Avoid printing 'Non-public channel' warnings in sshd(8), since the ssh(1) has sent incorrect channel numbers since ~2004 (this reverts a behaviour introduced in openssh-5.1; closes: #496017). * Update to GSSAPI patch from http://www.sxw.org.uk/computing/patches/openssh-5.2p1-gsskex-all-20090726.patch, including cascading credentials support (LP: #416958).
Diffstat (limited to 'loginrec.c')
-rw-r--r--loginrec.c139
1 files changed, 66 insertions, 73 deletions
diff --git a/loginrec.c b/loginrec.c
index b41114198..f4af06736 100644
--- a/loginrec.c
+++ b/loginrec.c
@@ -1456,25 +1456,14 @@ syslogin_write_entry(struct logininfo *li)
1456 **/ 1456 **/
1457 1457
1458#ifdef USE_LASTLOG 1458#ifdef USE_LASTLOG
1459#define LL_FILE 1
1460#define LL_DIR 2
1461#define LL_OTHER 3
1462
1463static void
1464lastlog_construct(struct logininfo *li, struct lastlog *last)
1465{
1466 /* clear the structure */
1467 memset(last, '\0', sizeof(*last));
1468
1469 line_stripname(last->ll_line, li->line, sizeof(last->ll_line));
1470 strlcpy(last->ll_host, li->hostname,
1471 MIN_SIZEOF(last->ll_host, li->hostname));
1472 last->ll_time = li->tv_sec;
1473}
1474 1459
1460#if !defined(LASTLOG_WRITE_PUTUTXLINE) || !defined(HAVE_GETLASTLOGXBYNAME)
1461/* open the file (using filemode) and seek to the login entry */
1475static int 1462static int
1476lastlog_filetype(char *filename) 1463lastlog_openseek(struct logininfo *li, int *fd, int filemode)
1477{ 1464{
1465 off_t offset;
1466 char lastlog_file[1024];
1478 struct stat st; 1467 struct stat st;
1479 1468
1480 if (stat(LASTLOG_FILE, &st) != 0) { 1469 if (stat(LASTLOG_FILE, &st) != 0) {
@@ -1482,34 +1471,12 @@ lastlog_filetype(char *filename)
1482 LASTLOG_FILE, strerror(errno)); 1471 LASTLOG_FILE, strerror(errno));
1483 return (0); 1472 return (0);
1484 } 1473 }
1485 if (S_ISDIR(st.st_mode)) 1474 if (S_ISDIR(st.st_mode)) {
1486 return (LL_DIR);
1487 else if (S_ISREG(st.st_mode))
1488 return (LL_FILE);
1489 else
1490 return (LL_OTHER);
1491}
1492
1493
1494/* open the file (using filemode) and seek to the login entry */
1495static int
1496lastlog_openseek(struct logininfo *li, int *fd, int filemode)
1497{
1498 off_t offset;
1499 int type;
1500 char lastlog_file[1024];
1501
1502 type = lastlog_filetype(LASTLOG_FILE);
1503 switch (type) {
1504 case LL_FILE:
1505 strlcpy(lastlog_file, LASTLOG_FILE,
1506 sizeof(lastlog_file));
1507 break;
1508 case LL_DIR:
1509 snprintf(lastlog_file, sizeof(lastlog_file), "%s/%s", 1475 snprintf(lastlog_file, sizeof(lastlog_file), "%s/%s",
1510 LASTLOG_FILE, li->username); 1476 LASTLOG_FILE, li->username);
1511 break; 1477 } else if (S_ISREG(st.st_mode)) {
1512 default: 1478 strlcpy(lastlog_file, LASTLOG_FILE, sizeof(lastlog_file));
1479 } else {
1513 logit("%s: %.100s is not a file or directory!", __func__, 1480 logit("%s: %.100s is not a file or directory!", __func__,
1514 LASTLOG_FILE); 1481 LASTLOG_FILE);
1515 return (0); 1482 return (0);
@@ -1522,7 +1489,7 @@ lastlog_openseek(struct logininfo *li, int *fd, int filemode)
1522 return (0); 1489 return (0);
1523 } 1490 }
1524 1491
1525 if (type == LL_FILE) { 1492 if (S_ISREG(st.st_mode)) {
1526 /* find this uid's offset in the lastlog file */ 1493 /* find this uid's offset in the lastlog file */
1527 offset = (off_t) ((long)li->uid * sizeof(struct lastlog)); 1494 offset = (off_t) ((long)li->uid * sizeof(struct lastlog));
1528 1495
@@ -1535,52 +1502,74 @@ lastlog_openseek(struct logininfo *li, int *fd, int filemode)
1535 1502
1536 return (1); 1503 return (1);
1537} 1504}
1505#endif /* !LASTLOG_WRITE_PUTUTXLINE || !HAVE_GETLASTLOGXBYNAME */
1538 1506
1539static int 1507#ifdef LASTLOG_WRITE_PUTUTXLINE
1540lastlog_perform_login(struct logininfo *li) 1508int
1509lastlog_write_entry(struct logininfo *li)
1541{ 1510{
1542 struct lastlog last; 1511 switch(li->type) {
1543 int fd; 1512 case LTYPE_LOGIN:
1544 1513 return 1; /* lastlog written by pututxline */
1545 /* create our struct lastlog */ 1514 default:
1546 lastlog_construct(li, &last); 1515 logit("lastlog_write_entry: Invalid type field");
1547 1516 return 0;
1548 if (!lastlog_openseek(li, &fd, O_RDWR|O_CREAT))
1549 return (0);
1550
1551 /* write the entry */
1552 if (atomicio(vwrite, fd, &last, sizeof(last)) != sizeof(last)) {
1553 close(fd);
1554 logit("%s: Error writing to %s: %s", __func__,
1555 LASTLOG_FILE, strerror(errno));
1556 return (0);
1557 } 1517 }
1558
1559 close(fd);
1560 return (1);
1561} 1518}
1562 1519#else /* LASTLOG_WRITE_PUTUTXLINE */
1563int 1520int
1564lastlog_write_entry(struct logininfo *li) 1521lastlog_write_entry(struct logininfo *li)
1565{ 1522{
1523 struct lastlog last;
1524 int fd;
1525
1566 switch(li->type) { 1526 switch(li->type) {
1567 case LTYPE_LOGIN: 1527 case LTYPE_LOGIN:
1568 return (lastlog_perform_login(li)); 1528 /* create our struct lastlog */
1529 memset(&last, '\0', sizeof(last));
1530 line_stripname(last.ll_line, li->line, sizeof(last.ll_line));
1531 strlcpy(last.ll_host, li->hostname,
1532 MIN_SIZEOF(last.ll_host, li->hostname));
1533 last.ll_time = li->tv_sec;
1534
1535 if (!lastlog_openseek(li, &fd, O_RDWR|O_CREAT))
1536 return (0);
1537
1538 /* write the entry */
1539 if (atomicio(vwrite, fd, &last, sizeof(last)) != sizeof(last)) {
1540 close(fd);
1541 logit("%s: Error writing to %s: %s", __func__,
1542 LASTLOG_FILE, strerror(errno));
1543 return (0);
1544 }
1545
1546 close(fd);
1547 return (1);
1569 default: 1548 default:
1570 logit("%s: Invalid type field", __func__); 1549 logit("%s: Invalid type field", __func__);
1571 return (0); 1550 return (0);
1572 } 1551 }
1573} 1552}
1553#endif /* LASTLOG_WRITE_PUTUTXLINE */
1574 1554
1575static void 1555#ifdef HAVE_GETLASTLOGXBYNAME
1576lastlog_populate_entry(struct logininfo *li, struct lastlog *last) 1556int
1557lastlog_get_entry(struct logininfo *li)
1577{ 1558{
1578 line_fullname(li->line, last->ll_line, sizeof(li->line)); 1559 struct lastlogx l, *ll;
1579 strlcpy(li->hostname, last->ll_host,
1580 MIN_SIZEOF(li->hostname, last->ll_host));
1581 li->tv_sec = last->ll_time;
1582}
1583 1560
1561 if ((ll = getlastlogxbyname(li->username, &l)) == NULL) {
1562 memset(&l, '\0', sizeof(l));
1563 ll = &l;
1564 }
1565 line_fullname(li->line, ll->ll_line, sizeof(li->line));
1566 strlcpy(li->hostname, ll->ll_host,
1567 MIN_SIZEOF(li->hostname, ll->ll_host));
1568 li->tv_sec = ll->ll_tv.tv_sec;
1569 li->tv_usec = ll->ll_tv.tv_usec;
1570 return (1);
1571}
1572#else /* HAVE_GETLASTLOGXBYNAME */
1584int 1573int
1585lastlog_get_entry(struct logininfo *li) 1574lastlog_get_entry(struct logininfo *li)
1586{ 1575{
@@ -1598,7 +1587,10 @@ lastlog_get_entry(struct logininfo *li)
1598 memset(&last, '\0', sizeof(last)); 1587 memset(&last, '\0', sizeof(last));
1599 /* FALLTHRU */ 1588 /* FALLTHRU */
1600 case sizeof(last): 1589 case sizeof(last):
1601 lastlog_populate_entry(li, &last); 1590 line_fullname(li->line, last.ll_line, sizeof(li->line));
1591 strlcpy(li->hostname, last.ll_host,
1592 MIN_SIZEOF(li->hostname, last.ll_host));
1593 li->tv_sec = last.ll_time;
1602 return (1); 1594 return (1);
1603 case -1: 1595 case -1:
1604 error("%s: Error reading from %s: %s", __func__, 1596 error("%s: Error reading from %s: %s", __func__,
@@ -1613,6 +1605,7 @@ lastlog_get_entry(struct logininfo *li)
1613 /* NOTREACHED */ 1605 /* NOTREACHED */
1614 return (0); 1606 return (0);
1615} 1607}
1608#endif /* HAVE_GETLASTLOGXBYNAME */
1616#endif /* USE_LASTLOG */ 1609#endif /* USE_LASTLOG */
1617 1610
1618#ifdef USE_BTMP 1611#ifdef USE_BTMP