utmp, wtmp
NAZWA
utmp, wtmp - zapisy o logowaniu
SKŁADNIA
#include
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 utmp.
Ostrze�żenie: utmp musi być niezapisywalnym plikiem, ponieważ wiele pro-
gramó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 zapisywalny dla użytkowników.
Plik ten jest sekwencją wpisów o postaci następującej struktury
zdeklarowanej w pliku nagłówkowym (należy zwrócić uwagę, że jest to
jedna z wielu definicji; szczegóły zależą od wersji libc):
#define UT_UNKNOWN 0
#define RUN_LVL 1
#define BOOT_TIME 2
#define NEW_TIME 3
#define OLD_TIME 4
#define INIT_PROCESS 5
#define LOGIN_PROCESS 6
#define USER_PROCESS 7
#define DEAD_PROCESS 8
#define ACCOUNTING 9
#define UT_LINESIZE 12
#define UT_NAMESIZE 32
#define UT_HOSTSIZE 256
struct exit_status {
short int e_termination; /* kod przerwania procesu. */
short int e_exit; /* kod zakończenia procesu. */
};
struct utmp {
short ut_type; /* rodzaj logowania */
pid_t ut_pid; /* PID procesu logującego */
char ut_line[UT_LINESIZE]; /* nazwa urządzenia tty - "/dev/" */
char ut_id[4]; /* id init lub skrót nazwy tty */
char ut_user[UT_NAMESIZE]; /* nazwa użytkownika */
char ut_host[UT_HOSTSIZE]; /* nazwa hosta dla zdalnego logowania */
struct exit_status ut_exit; /* kod zakończenia procesu
oznaczonego jako DEAD_PROCESS */
/* Pola ut_session i ut_tv muszą mieć ten sam rozmiar, gdy są
kompilowane 32- i 64-bitowo.Pozwala to dzielenie plików danych
pamięci współdzielonej pomiędzy aplikacjami 32- i 64-bitowymi*/
#if __WORDSIZE == 64 && defined __WORDSIZE_COMPAT32
int32_t ut_session; /* ID sesji, służy do okienkowania */
struct {
int32_t tv_sec; /* Sekundy */
int32_t tv_usec; /* Mikrosekundy */
} ut_tv; /* Czas utworzenia wpisu */
#else
long int ut_session; /* ID sesji, służy do okienkowania */
struct timeval ut_tv; /* Czas utworzenia wpisu */
#endif
int32_t ut_addr_v6[4]; /* Adres IP zdalnego komputera */
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 "�", 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 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.
getty(8) lokalizuje wpis po numerze PID, zmienia ut_type na LOGIN_PRO-
CESS, zmienia ut_time, ustawia ut_line i czeka na zestawienie
połączenia. Po autentykacji użytkownika, login(8) zmienia ut_type na
USER_PROCESS, zmienia ut_time i nadaje wartości ut_host i ut_addr.
Zależnie od wersji getty(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 ostatnich dwóch liter
/dev/ttyp%c lub używając p%d dla /dev/pts/%d. Jeśli znajdą dla tego id
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.
xdm(1) nie powinien tworzyć rekordu w utmp, ponieważ nie ma przy-
dzielonego terminala. Pozwalanie mu na utworzenie takowego spowoduje
błędy takie jak "finger: cannot stat /dev/machine.dom". Jednak powinien
on tworzyć wpisy wtmp, tak jak to czyni ftpd(8).
telnetd(8) ustawia wpis LOGIN_PROCESS i zostawia po prostu resztę pro-
gramowi login(8). 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 |/} loguje
nowy/stary 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). Żaden z tych programów nie tworzy tego pliku, więc jeśli
zostanie on usunięty, zapisy do niego zostaną wyłączone.
Proszę zauważyć, że na platformach, które mogą uruchamiać zarówno
32-bitowe, jaki 64-bitowe aplikacje (x86-64, ppc64, s390x itd.), rozmi-
ary pola ut_tvmusi być taki same 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. 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;
PLIKI
/var/run/utmp
/var/log/wtmp
ZGODNE Z
Wpisy utmp Linuksa nie są zgodne ani z v7/BSD ani z Systemem V, ale są
mieszaniną tych dwóch. v7/BSD ma mniej pól; najważniejszym problemem
jest brak ut_type, który powoduje że natywne programy v7/BSD wyświet-
lają (na przykład) wpisy dead lub login. Co więcej, nie ma pliku kon-
figuracyjnego, który przydziela rekordy sesjom. BSD tak robi, ponieważ
nie ma on pól 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. Czyszcze-
nie 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 uruchami-
anie 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 używa pola type tylko do ich zaznaczania i loguje komunikaty
informacyjne, takie jak np. "new time" w polu line. UT_UNKNOWN wydaje
się być wymyślone w Linuksie. System V nie ma pól ut_host czy
ut_addr_v6.
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.
Trzeba zwrócić uwagę, że struktura utmp z libc5 uległa zmianie w libc6.
Z tego powodu binaria korzystające ze starej struktury libc5 będą
uszkadzać /var/run/utmp i/lub /var/log/wtmp. System Debian zawiera
połataną wersję libc5, która korzysta z nowego formatu utmp. Natomiast
wciąż istnieje problem z wtmp, gdyż dostęp do tego pliku odbywa się w
libc5 bezpośrednio.
OGRANICZENIA
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.), rozmi-
ary pól w strukturze utmp muszą być takie same w trybie 32-bitowym, co
w 64-bitowym, Osiąga się to przez zmianę typu ut_session na int32_t,
ut_tv na strukturę z dwoma polami typu int32_t: tv_sec i tv_usec (Dlat-
ego, aby ją wypełnić, należy najpierw pobrać czas do rzeczywistej
struktury timeval, a następnie skopiować oba pola do ut_tv.)
BŁĘDY
Ta strona podręcznika została oparta na stronie z wersji libc5, rzeczy
mogą obecnie działać inaczej.
ZOBACZ TAKŻE
ac(1), date(1), last(1), login(1), who(1), getutent(3), updwtmp(3),
init(8)