~ubuntu-branches/ubuntu/raring/shadow/raring-proposed

« back to all changes in this revision

Viewing changes to src/lastlog.c

  • Committer: Bazaar Package Importer
  • Author(s): Kees Cook
  • Date: 2009-05-05 09:45:21 UTC
  • mfrom: (1.1.6 upstream)
  • Revision ID: james.westby@ubuntu.com-20090505094521-wpk2wn3q7957tlah
Tags: 1:4.1.3.1-1ubuntu1
* Merge from debian unstable, remaining changes:
  - Ubuntu specific:
    + debian/login.defs: use SHA512 by default for password crypt routine.
  - debian/patches/stdout-encrypted-password.patch: chpasswd can report
    password hashes on stdout (debian bug 505640).
  - debian/login.pam: Enable SELinux support (debian bug 527106).
  - debian/securetty.linux: support Freescale MX-series (debian bug 527095).
* Add debian/patches/300_lastlog_failure: fixed upstream (debian bug 524873).
* Drop debian/patches/593_omit_lastchange_field_if_clock_is_misset: fixed
  upstream.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 * Copyright 1989 - 1994, Julianne Frances Haugh
 
2
 * Copyright (c) 1989 - 1994, Julianne Frances Haugh
 
3
 * Copyright (c) 1996 - 2000, Marek Michałkiewicz
 
4
 * Copyright (c) 2000 - 2006, Tomasz Kłoczko
 
5
 * Copyright (c) 2007 - 2009, Nicolas François
3
6
 * All rights reserved.
4
7
 *
5
8
 * Redistribution and use in source and binary forms, with or without
10
13
 * 2. Redistributions in binary form must reproduce the above copyright
11
14
 *    notice, this list of conditions and the following disclaimer in the
12
15
 *    documentation and/or other materials provided with the distribution.
13
 
 * 3. Neither the name of Julianne F. Haugh nor the names of its contributors
14
 
 *    may be used to endorse or promote products derived from this software
15
 
 *    without specific prior written permission.
 
16
 * 3. The name of the copyright holders or contributors may not be used to
 
17
 *    endorse or promote products derived from this software without
 
18
 *    specific prior written permission.
16
19
 *
17
 
 * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND
18
 
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
 
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
 
 * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE
21
 
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
 
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23
 
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24
 
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
 
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26
 
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27
 
 * SUCH DAMAGE.
 
20
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 
21
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 
22
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 
23
 * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT
 
24
 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 
25
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 
26
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 
27
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 
28
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 
29
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 
30
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
31
 */
29
32
 
30
33
#include <config.h>
31
34
 
32
 
#ident "$Id: lastlog.c 1751 2008-02-03 16:28:03Z nekral-guest $"
 
35
#ident "$Id: lastlog.c 2502 2009-03-13 22:20:20Z nekral-guest $"
33
36
 
34
37
#include <getopt.h>
35
38
#include <lastlog.h>
38
41
#include <sys/stat.h>
39
42
#include <sys/types.h>
40
43
#include <time.h>
 
44
#include <assert.h>
41
45
#include "defines.h"
42
46
#include "prototypes.h"
 
47
 
43
48
/*
44
49
 * Needed for MkLinux DR1/2/2.1 - J.
45
50
 */
46
51
#ifndef LASTLOG_FILE
47
52
#define LASTLOG_FILE "/var/log/lastlog"
48
53
#endif
 
54
 
49
55
/*
50
56
 * Global variables
51
57
 */
52
58
static FILE *lastlogfile;       /* lastlog file stream */
53
 
static long umin;               /* if uflg, only display users with uid >= umin */
54
 
static long umax;               /* if uflg, only display users with uid <= umax */
 
59
static unsigned long umin;      /* if uflg and has_umin, only display users with uid >= umin */
 
60
static bool has_umin = false;
 
61
static unsigned long umax;      /* if uflg and has_umax, only display users with uid <= umax */
 
62
static bool has_umax = false;
55
63
static int days;                /* number of days to consider for print command */
56
64
static time_t seconds;          /* that number of days in seconds */
57
65
static int inverse_days;        /* number of days to consider for print command */
58
66
static time_t inverse_seconds;  /* that number of days in seconds */
59
 
 
60
 
 
61
 
static int uflg = 0;            /* print only an user of range of users */
62
 
static int tflg = 0;            /* print is restricted to most recent days */
63
 
static int bflg = 0;            /* print excludes most recent days */
64
 
static struct lastlog lastlog;  /* scratch structure to play with ... */
 
67
static struct stat statbuf;     /* fstat buffer for file size */
 
68
 
 
69
 
 
70
static bool uflg = false;       /* print only an user of range of users */
 
71
static bool tflg = false;       /* print is restricted to most recent days */
 
72
static bool bflg = false;       /* print excludes most recent days */
65
73
static struct passwd *pwent;
66
74
 
67
75
#define NOW     (time ((time_t *) 0))
81
89
 
82
90
static void print_one (const struct passwd *pw)
83
91
{
84
 
        static int once;
 
92
        static bool once = false;
85
93
        char *cp;
86
94
        struct tm *tm;
87
95
        time_t ll_time;
 
96
        off_t offset;
 
97
        struct lastlog ll;
88
98
 
89
99
#ifdef HAVE_STRFTIME
90
100
        char ptime[80];
91
101
#endif
92
102
 
93
 
        if (!pw)
94
 
                return;
95
 
 
 
103
        if (NULL == pw) {
 
104
                return;
 
105
        }
 
106
 
 
107
 
 
108
        offset = pw->pw_uid * sizeof (ll);
 
109
 
 
110
        if (offset <= (statbuf.st_size - sizeof (ll))) {
 
111
                /* fseeko errors are not really relevant for us. */
 
112
                assert ( fseeko (lastlogfile, offset, SEEK_SET) == 0 );
 
113
                /* lastlog is a sparse file. Even if no entries were
 
114
                 * entered for this user, which should be able to get the
 
115
                 * empty entry in this case.
 
116
                 */
 
117
                if (fread ((char *) &ll, sizeof (ll), 1, lastlogfile) != 1) {
 
118
                        fprintf (stderr,
 
119
                                 _("lastlog: Failed to get the entry for UID %d\n"),
 
120
                                 pw->pw_uid);
 
121
                        exit (1);
 
122
                }
 
123
        } else {
 
124
                /* Outsize of the lastlog file.
 
125
                 * Behave as if there were a missing entry (same behavior
 
126
                 * as if we were reading an non existing entry in the
 
127
                 * sparse lastlog file).
 
128
                 */
 
129
                memzero (&ll, sizeof (ll));
 
130
        }
 
131
 
 
132
        /* Filter out entries that do not match with the -t or -b options */
 
133
        if (tflg && ((NOW - ll.ll_time) > seconds)) {
 
134
                return;
 
135
        }
 
136
 
 
137
        if (bflg && ((NOW - ll.ll_time) < inverse_seconds)) {
 
138
                return;
 
139
        }
 
140
 
 
141
        /* Print the header only once */
96
142
        if (!once) {
97
143
#ifdef HAVE_LL_HOST
98
144
                puts (_("Username         Port     From             Latest"));
99
145
#else
100
146
                puts (_("Username                Port     Latest"));
101
147
#endif
102
 
                once++;
 
148
                once = true;
103
149
        }
104
 
        ll_time = lastlog.ll_time;
 
150
 
 
151
        ll_time = ll.ll_time;
105
152
        tm = localtime (&ll_time);
106
153
#ifdef HAVE_STRFTIME
107
154
        strftime (ptime, sizeof (ptime), "%a %b %e %H:%M:%S %z %Y", tm);
111
158
        cp[24] = '\0';
112
159
#endif
113
160
 
114
 
        if (lastlog.ll_time == (time_t) 0)
 
161
        if (ll.ll_time == (time_t) 0) {
115
162
                cp = _("**Never logged in**\0");
 
163
        }
116
164
 
117
165
#ifdef HAVE_LL_HOST
118
 
        printf ("%-16s %-8.8s %-16.16s %s\n", pw->pw_name,
119
 
                lastlog.ll_line, lastlog.ll_host, cp);
 
166
        printf ("%-16s %-8.8s %-16.16s %s\n",
 
167
                pw->pw_name, ll.ll_line, ll.ll_host, cp);
120
168
#else
121
 
        printf ("%-16s\t%-8.8s %s\n", pw->pw_name, lastlog.ll_line, cp);
 
169
        printf ("%-16s\t%-8.8s %s\n",
 
170
                pw->pw_name, ll.ll_line, cp);
122
171
#endif
123
172
}
124
173
 
125
174
static void print (void)
126
175
{
127
 
        off_t offset;
128
 
        uid_t user;
129
 
 
130
 
        setpwent ();
131
 
        while ((pwent = getpwent ())) {
132
 
                user = pwent->pw_uid;
133
 
                if (uflg &&
134
 
                    ((umin != -1 && user < (uid_t)umin) ||
135
 
                     (umax != -1 && user > (uid_t)umax)))
136
 
                        continue;
137
 
                offset = user * sizeof lastlog;
138
 
 
139
 
                fseeko (lastlogfile, offset, SEEK_SET);
140
 
                if (fread ((char *) &lastlog, sizeof lastlog, 1,
141
 
                           lastlogfile) != 1)
142
 
                        continue;
143
 
 
144
 
                if (tflg && NOW - lastlog.ll_time > seconds)
145
 
                        continue;
146
 
 
147
 
                if (bflg && NOW - lastlog.ll_time < inverse_seconds)
148
 
                        continue;
149
 
 
150
 
                print_one (pwent);
 
176
        if (uflg && has_umin && has_umax && (umin == umax)) {
 
177
                print_one (getpwuid ((uid_t)umin));
 
178
        } else {
 
179
                setpwent ();
 
180
                while ( (pwent = getpwent ()) != NULL ) {
 
181
                        if (   uflg
 
182
                            && (   (has_umin && (pwent->pw_uid < (uid_t)umin))
 
183
                                || (has_umax && (pwent->pw_uid > (uid_t)umax)))) {
 
184
                                continue;
 
185
                        }
 
186
                        print_one (pwent);
 
187
                }
 
188
                endpwent ();
151
189
        }
152
190
}
153
191
 
154
192
int main (int argc, char **argv)
155
193
{
156
 
        setlocale (LC_ALL, "");
157
 
        bindtextdomain (PACKAGE, LOCALEDIR);
158
 
        textdomain (PACKAGE);
 
194
        (void) setlocale (LC_ALL, "");
 
195
        (void) bindtextdomain (PACKAGE, LOCALEDIR);
 
196
        (void) textdomain (PACKAGE);
159
197
 
160
198
        {
161
199
                int c;
167
205
                        {NULL, 0, NULL, '\0'}
168
206
                };
169
207
 
170
 
                while ((c =
171
 
                        getopt_long (argc, argv, "ht:b:u:", longopts,
172
 
                                     NULL)) != -1) {
 
208
                while ((c = getopt_long (argc, argv, "ht:b:u:", longopts,
 
209
                                         NULL)) != -1) {
173
210
                        switch (c) {
174
211
                        case 'h':
175
212
                                usage ();
176
213
                                break;
177
214
                        case 't':
178
 
                                days = atoi (optarg);
179
 
                                seconds = days * DAY;
180
 
                                tflg++;
 
215
                                days = atoi (optarg); /* FIXME */
 
216
                                seconds = (time_t) days * DAY;
 
217
                                tflg = true;
181
218
                                break;
182
219
                        case 'b':
183
 
                                inverse_days = atoi (optarg);
184
 
                                inverse_seconds = inverse_days * DAY;
185
 
                                bflg++;
 
220
                                inverse_days = atoi (optarg); /* FIXME */
 
221
                                inverse_seconds = (time_t) inverse_days * DAY;
 
222
                                bflg = true;
186
223
                                break;
187
224
                        case 'u':
188
225
                                /*
192
229
                                 *  - a numerical login ID
193
230
                                 *  - a range (-x, x-, x-y)
194
231
                                 */
195
 
                                uflg++;
196
 
                                pwent = xgetpwnam (optarg);
 
232
                                uflg = true;
 
233
                                /* local, no need for xgetpwnam */
 
234
                                pwent = getpwnam (optarg);
197
235
                                if (NULL != pwent) {
198
 
                                        umin = pwent->pw_uid;
 
236
                                        umin = (unsigned long) pwent->pw_uid;
 
237
                                        has_umin = true;
199
238
                                        umax = umin;
 
239
                                        has_umax = true;
200
240
                                } else {
201
 
                                        char *endptr = NULL;
202
 
                                        long int user;
203
 
                                        user = strtol(optarg, &endptr, 10);
204
 
                                        if (*optarg != '\0' && *endptr == '\0') {
205
 
                                                if (user < 0) {
206
 
                                                        /* -<userid> */
207
 
                                                        umin = -1;
208
 
                                                        umax = -user;
209
 
                                                } else {
210
 
                                                        /* <userid> */
211
 
                                                        umin = user;
212
 
                                                        umax = user;
213
 
                                                }
214
 
                                        } else if (endptr[0] == '-' && endptr[1] == '\0') {
215
 
                                                /* <userid>- */
216
 
                                                umin = user;
217
 
                                                umax = -1;
218
 
                                        } else if (*endptr == '-') {
219
 
                                                /* <userid>-<userid> */
220
 
                                                umin = user;
221
 
                                                umax = atol(endptr+1);
222
 
                                        } else {
 
241
                                        if (getrange (optarg,
 
242
                                                      &umin, &has_umin,
 
243
                                                      &umax, &has_umax) == 0) {
223
244
                                                fprintf (stderr,
224
 
                                                         _("Unknown user or range: %s\n"),
225
 
                                                         optarg);
 
245
                                                         _("lastlog: Unknown user or range: %s\n"),
 
246
                                                         optarg);
226
247
                                                exit (1);
227
248
                                        }
228
249
                                }
246
267
        }
247
268
 
248
269
        print ();
 
270
        /* Get the laslog size */
 
271
        if (fstat (fileno (lastlogfile), &statbuf) != 0) {
 
272
                fprintf (stderr,
 
273
                         _("lastlog: Cannot get the size of %s: %s\n"),
 
274
                         LASTLOG_FILE, strerror (errno));
 
275
                exit (1);
 
276
        }
 
277
 
249
278
        fclose (lastlogfile);
250
279
        exit (0);
251
280
}
 
281