utmp(5) zapisy o logowaniu

Other Alias

wtmp

SKŁADNIA

#include <utmp.h>

OPIS

Plik utmp umożliwia znalezienie informacji o tym, kto w danej chwili korzysta z systemu. Z systemu może korzystać więcej użytkowników, ponieważ nie wszystkie programy zapisują informacje do pliku utmp.

Ostrzeżenie: utmp nie może mieć ustawionego prawa do zapisywania dla wszystkich użytkowników, ponieważ wiele programów systemowych (głupio) polega na jego integralności. Istnieje ryzyko sfałszowania logów systemowych i modyfikacji plików systemowych, jeśli utmp będzie modyfikowalny przez użytkowników innych niż właściciel tego pliku i użytkownicy należący do grupy, do której należy właściciel pliku.

Plik jest sekwencją wpisów, z których każdy ma postać następującej struktury utmpzdeklarowanej w pliku nagłówkowym <utmp.h> (należy zwrócić uwagę, że jest to jedna z wielu definicji; szczegóły zależą od wersji libc):


/* Wartości pola ut_field poniżej */
#define EMPTY         0 /* Rekord nie zawiera poprawnej informacji
                           (poprzednio znany jako UT_UNKNOWN pod Linuksem) */
#define RUN_LVL       1 /* Zmiana systemowych poziomów uruchomieniowych
                           patrz init(8)) */
#define BOOT_TIME     2 /* Czas uruchomienia systemu (w ut_tv) */
#define NEW_TIME      3 /* Czas po zmianie zegara systemowego
                           (w ut_tv) */
#define OLD_TIME      4 /* Czas przed zmianą zegara systemowego
                           (w ut_tv) */
#define INIT_PROCESS  5 /* Proces uruchomiony przez init(8) */
#define LOGIN_PROCESS 6 /* Lider sesji procesów logowania użytkownika */
#define USER_PROCESS  7 /* Zwykły proces */
#define DEAD_PROCESS  8 /* Proces zakończony */
#define ACCOUNTING    9 /* Niezaimplementowane */
#define UT_LINESIZE      32
#define UT_NAMESIZE      32
#define UT_HOSTSIZE     256
struct exit_status {              /* Typ dla ut_exit, patrz poniżej */
    short int e_termination;      /* Kod przerwania procesu */
    short int e_exit;             /* Kod wyjścia procesu */
};
struct utmp {
    short   ut_type;              /* Typ recordu */
    pid_t   ut_pid;               /* ID procesu logowania */
    char    ut_line[UT_LINESIZE]; /* Nazwa urządzenie terminala - "/dev/" */
    char    ut_id[4];             /* Przyrostek nazwy terminala,
                                     lub ID linii inittab(5) */
    char    ut_user[UT_NAMESIZE]; /* Nazwa użytkownika */
    char    ut_host[UT_HOSTSIZE]; /* Nazwa komputera dla zdalnego logowania lub
                                     wersja jądra dla komunikatów o zmianach
                                     systemowych poziomów uruchomieniowych */
    struct  exit_status ut_exit;  /* Kod zakończenia procesu oznaczonego
                                     jako DEAD_PROCESS; nieużywane
                                     przez init(8) pod Linuksem */
    /* Pola ut_session i ut_tv  muszą mieć ten sam rozmiar w środowiskach
       32- i 64-bitowych. Pozwala to na współdzielenie plików i pamięci dzielone
       pomiędzy aplikacjami 32- i 64-bitowymi */
#if __WORDSIZE == 64 && defined __WORDSIZE_COMPAT32
    int32_t ut_session;           /* ID sesji (getsid(2)),
                                     używane przez GUI */
    struct {
        int32_t tv_sec;           /* Sekundy */
        int32_t tv_usec;          /* Mikrosekundy */
    } ut_tv;                      /* Czas utworzenia wpisu */
#else
     long   ut_session;           /* ID sesji  */
     struct timeval ut_tv;        /* Czas utworzenia wpisu */
#endif
    int32_t ut_addr_v6[4];        /* Adres internetowy zdalnego
                                     komputera; adres IPv4 używa
                                     tylko ut_addr_v6[0] */
    char __unused[20];            /* Zarezerwowane na przyszłość */
};
/* Dla zgodności w wcześniejszymi wersjami */
#define ut_name ut_user
#ifndef _NO_UT_TIME
#define ut_time ut_tv.tv_sec
#endif
#define ut_xtime ut_tv.tv_sec
#define ut_addr ut_addr_v6[0]

Struktura ta podaje nazwę pliku specjalnego skojarzonego z terminalem użytkownika, nazwę użytkownika i czas zalogowania w postaci time(2). Pola tekstowe są zakończone przez bajt NULL ("\0"), jeżeli są krótsze niż rozmiar pola.

Pierwsze wpisy, jakie kiedykolwiek utworzono, pochodzą od init(8) przetwarzającego inittab(5). Zanim jakikolwiek wpis zostanie utworzony, init(8) czyści utmp przez wpisanie DEAD_PROCESS do ut_type, wypełniając ut_user, ut_host i ut_time bajtami NULL we wszystkich rekordach, w których ut_type nie jest ustawione na DEAD_PROCESS lub RUN_LVL i dla których nie istnieje proces o PID równym ut_pid. Jeśli nie znajdzie się żaden pusty rekord z wymaganym ut_id, init(8) tworzy nowy. Wpisuje do niego ut_id z inittab, ut_pid i ut_time nadaje bieżące wartości, a ut_type nadaje wartość INIT_PROCESS.

mingetty(8) (lub agetty(8)) lokalizuje wpis po numerze PID, zmienia ut_type na LOGIN_PROCESS, zmienia ut_time, ustawia ut_line i czeka na zestawienie połączenia. Po autentykacji użytkownika, login(1) zmienia ut_type na USER_PROCESS, zmienia ut_time i nadaje wartości ut_host i ut_addr. Zależnie od wersji mingetty(8) (lub agetty(8)) i login(8), rekordy mogą być wyszukiwane na podstawie ut_line zamiast preferowanego ut_pid.

Gdy init(8) stwierdzi, że proces zakończył pracę, to znajduje jego wpis utmp według ut_pid, ustawia ut_type na DEAD_PROCESS i wypełnia ut_user, ut_host oraz ut_time bajtami NULL.

xterm(1) i inne emulatory terminali tworzą bezpośrednio rekord USER_PROCESS i generują ut_id, używając końcowej części nazwy terminala (czyli znaków występujących po /dev/[pt]ty). Jeśli znajdą dla tego ID terminala wpis DEAD_PROCESS, utylizują go, w innym wypadku tworzą nowy wpis. Jeśli mogą, zaznaczają go jako DEAD_PROCESS podczas kończenia pracy i jest zalecane, by zerowały również ut_line, ut_time, ut_user oraz ut_host.

telnetd(8) ustawia wpis LOGIN_PROCESS i zostawia resztę programowi login(1). Po zakończeniu sesji telnetu, telnetd(8) czyści utmp w opisany sposób.

Plik wtmp śledzi wszystkie zalogowania i wylogowania. Jego format jest taki jak utmp, poza tym, że pusta nazwa użytkownika wskazuje na jego wylogowanie z odpowiedniego terminala. Co więcej, nazwa terminala ~ w połączeniu z nazwą użytkownika shutdown czy reboot wskazuje na zamknięcie lub restart systemu, a para nazw terminali |/} zapisuje stary i nowy czas systemowy w przypadku jego zmiany za pomocą date(1). wtmp jest obsługiwane przez login(1), init(1) oraz niektóre wersje getty(1) (np. mingetty(8) lub agetty(8)). Żaden z tych programów nie tworzy tego pliku, więc jeśli zostanie usunięty, zapisy do niego zostaną wyłączone.

PLIKI

/var/run/utmp
/var/log/wtmp

ZGODNE Z

POSIX.1 nie definiuje struktury utmp, ale ma utmpx z definicjami pól ut_type, ut_pid, ut_line, ut_id, ut_user, and ut_tv. POSIX.1 nie określa długości pól ut_line i ut_user.

Pod Linuksem struktura utmpx jest zdefiniowana tak samo jak struktura utmp.

Porównanie z historycznymi systemami

Wpisy utmp Linuksa nie są zgodne ani z v7/BSD ani z Systemem V, ale są mieszaniną tych dwóch.

v7/BSD zawiera mniej pól; najważniejszym problemem jest brak ut_type, który powoduje że natywne programy v7/BSD wyświetlają (na przykład) wpisy DEAD_PROCESS lub LOGIN_PROCESS. Co więcej, nie ma pliku konfiguracyjnego, który przydziela rekordy sesjom. BSD tak robi z powodu braku pola ut_id.

W Linuksie (tak jak w Systemie V), pole ut_id rekordu nigdy nie ulega zmianie, kiedy raz zostanie mu nadana wartość, co rezerwuje ten rekord bez potrzeby pliku konfiguracyjnego. Czyszczenie ut_id może prowadzić do sytuacji wyścigu, których skutkiem będą uszkodzone wpisy w utmp i potencjalne dziury w bezpieczeństwie. Czyszczenie wymienionych wyżej pól przez wypełnianie ich bajtami NULL nie jest wymagane przy semantyce Systemu V, lecz pozwala na uruchamianie wielu programów, które zakładają semantykę BSD, a nie modyfikują utmp. Linux używa konwencji BSD dla zawartości pola line, jak opisano wyżej.

System V nie ma pól ut_host ani ut_addr_v6.

UWAGI

W przeciwieństwie do wielu innych systemów, gdzie utmp można wyłączyć przez usunięcie tego pliku, w Linuksie utmp zawsze musi istnieć. W celu wyłączenia who(1) należy jedynie uniemożliwić odczyt utmp dla całego świata.

Format pliku jest zależny od maszyny, więc jest zalecane, by plik był przetwarzany tylko na maszynie, na której został utworzony.

Proszę zauważyć, że na platformach, które mogą uruchamiać zarówno 32-bitowe, jaki 64-bitowe aplikacje (x86-64, ppc64, s390x itd.), rozmiar pola ut_tv musi być taki sam w trybie 32-bitowym, co w 64-bitowym. Podobnie jest z polami ut_session i ut_time, jeśli są obecne. Pozwala to na dzielenie plików danych i pamięci współdzielonej pomiędzy aplikacjami 32- i 64-bitowymi. Osiągnięto to zmieniając typ ut_session na int32_t, a typ ut_tv na strukturę zawierającą dwa pola o typie int32_t: tv_sec and tv_usec. Ponieważ ut_tv może nie być takie samo jak struct timeval, to zamiast wywoływania:


gettimeofday((struct timeval *) &ut.ut_tv, NULL);

zaleca się używanie poniższej metody do ustawiania wartości w tym polu:


struct utmp ut; struct timeval tv; gettimeofday(&tv, NULL); ut.ut_tv.tv_sec = tv.tv_sec; ut.ut_tv.tv_usec = tv.tv_usec;

O STRONIE

Angielska wersja tej strony pochodzi z wydania 3.71 projektu Linux man-pages. Opis projektu, informacje dotyczące zgłaszania błędów, oraz najnowszą wersję oryginału można znaleźć pod adresem http://www.kernel.org/doc/man-pages/.

TŁUMACZENIE

Autorami polskiego tłumaczenia niniejszej strony podręcznika man są: Przemek Borys (PTM) <[email protected]>, Robert Luberda <[email protected]> i Michał Kułach <[email protected]>.

Polskie tłumaczenie jest częścią projektu manpages-pl; uwagi, pomoc, zgłaszanie błędów na stronie http://sourceforge.net/projects/manpages-pl/. Jest zgodne z wersją 3.71 oryginału.