summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>2009-02-12 13:12:21 +1100
committerDamien Miller <djm@mindrot.org>2009-02-12 13:12:21 +1100
commit20e231f9f8445ad072b319c9c47f3d9897a1f284 (patch)
tree314a7d0585cb194910d066ca3a750b056ef911e8
parent2de762456e8cdb92b85c1e573cbf2b4b70eee847 (diff)
- (djm) [configure.ac loginrec.c] bz#1421: fix lastlog support for OSX.
OSX provides a getlastlogxbyname function that automates the reading of a lastlog file. Also, the pututxline function will update lastlog so there is no need for loginrec.c to do it explicitly. Collapse some overly verbose code while I'm in there.
-rw-r--r--ChangeLog9
-rw-r--r--configure.ac8
-rw-r--r--loginrec.c139
3 files changed, 79 insertions, 77 deletions
diff --git a/ChangeLog b/ChangeLog
index 8bec9d153..124924b71 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,11 @@
120090212 120090205
2 - (djm) [sshpty.c] bz#1419: OSX uses cloning ptys that automagically 2 - (djm) [sshpty.c] bz#1419: OSX uses cloning ptys that automagically
3 set ownership and modes, so avoid explicitly setting them 3 set ownership and modes, so avoid explicitly setting them
4 - (djm) [configure.ac loginrec.c] bz#1421: fix lastlog support for OSX.
5 OSX provides a getlastlogxbyname function that automates the reading of
6 a lastlog file. Also, the pututxline function will update lastlog so
7 there is no need for loginrec.c to do it explicitly. Collapse some
8 overly verbose code while I'm in there.
4 9
520090201 1020090201
6 - (dtucker) [defines.h sshconnect.c] INET6_ADDRSTRLEN is now needed in 11 - (dtucker) [defines.h sshconnect.c] INET6_ADDRSTRLEN is now needed in
@@ -5118,5 +5123,5 @@
5118 OpenServer 6 and add osr5bigcrypt support so when someone migrates 5123 OpenServer 6 and add osr5bigcrypt support so when someone migrates
5119 passwords between UnixWare and OpenServer they will still work. OK dtucker@ 5124 passwords between UnixWare and OpenServer they will still work. OK dtucker@
5120 5125
5121$Id: ChangeLog,v 1.5184 2009/02/12 01:19:20 djm Exp $ 5126$Id: ChangeLog,v 1.5185 2009/02/12 02:12:21 djm Exp $
5122 5127
diff --git a/configure.ac b/configure.ac
index 94589ddc7..242dea0dc 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,4 +1,4 @@
1# $Id: configure.ac,v 1.413 2009/01/08 04:50:09 tim Exp $ 1# $Id: configure.ac,v 1.414 2009/02/12 02:12:22 djm Exp $
2# 2#
3# Copyright (c) 1999-2004 Damien Miller 3# Copyright (c) 1999-2004 Damien Miller
4# 4#
@@ -15,7 +15,7 @@
15# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 16
17AC_INIT(OpenSSH, Portable, openssh-unix-dev@mindrot.org) 17AC_INIT(OpenSSH, Portable, openssh-unix-dev@mindrot.org)
18AC_REVISION($Revision: 1.413 $) 18AC_REVISION($Revision: 1.414 $)
19AC_CONFIG_SRCDIR([ssh.c]) 19AC_CONFIG_SRCDIR([ssh.c])
20 20
21AC_CONFIG_HEADER(config.h) 21AC_CONFIG_HEADER(config.h)
@@ -477,6 +477,8 @@ main() { if (NSVersionOfRunTimeLibrary("System") >= (60 << 16))
477 AC_CHECK_DECL(AU_IPv4, [], 477 AC_CHECK_DECL(AU_IPv4, [],
478 AC_DEFINE(AU_IPv4, 0, [System only supports IPv4 audit records]) 478 AC_DEFINE(AU_IPv4, 0, [System only supports IPv4 audit records])
479 [#include <bsm/audit.h>] 479 [#include <bsm/audit.h>]
480 AC_DEFINE(LASTLOG_WRITE_PUTUTXLINE, 1,
481 [Define if pututxline updates lastlog too])
480 ) 482 )
481 ;; 483 ;;
482*-*-dragonfly*) 484*-*-dragonfly*)
@@ -1508,6 +1510,8 @@ AC_CHECK_FUNCS(utmpname)
1508dnl Checks for utmpx functions 1510dnl Checks for utmpx functions
1509AC_CHECK_FUNCS(endutxent getutxent getutxid getutxline pututxline ) 1511AC_CHECK_FUNCS(endutxent getutxent getutxid getutxline pututxline )
1510AC_CHECK_FUNCS(setutxent utmpxname) 1512AC_CHECK_FUNCS(setutxent utmpxname)
1513dnl Checks for lastlog functions
1514AC_CHECK_FUNCS(getlastlogxbyname)
1511 1515
1512AC_CHECK_FUNC(daemon, 1516AC_CHECK_FUNC(daemon,
1513 [AC_DEFINE(HAVE_DAEMON, 1, [Define if your libraries define daemon()])], 1517 [AC_DEFINE(HAVE_DAEMON, 1, [Define if your libraries define daemon()])],
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