מידע משתמש וקבוצה

getpwnam#

לחפש את רשומת ה־passwd של משתמש לפי שם כניסה.

getpwnam עוטף את הקריאה getpwnam(3) של ספריית C של המערכת. יש להעביר שם כניסה כמו "root" או "alice"; מוחזרת רשומת ה־passwd עבור אותו משתמש, או רשימה ריקה / undef אם משתמש כזה אינו קיים. צורת ההחזרה תלויה בהקשר: הקשר רשימה מחזיר כל שדה של הרשומה; הקשר סקלרי מחזיר ערך שימושי יחיד - עבור getpwnam במפורש, ה־UID המספרי.

תקציר#

getpwnam NAME

מה מקבלים בחזרה#

הקשר רשימה מחזיר רשימה של 10 אלמנטים שמשקפת את struct passwd בתוספת התוספות של BSD:

my ($name,    $passwd, $uid,  $gid,   $quota,
    $comment, $gcos,   $dir,  $shell, $expire) = getpwnam($login);
  • $name - שם כניסה (אותה מחרוזת שהעברת)

  • $passwd - סיסמה מוצפנת, או "x" / "*" במערכות עם shadow-password. tainted תחת -T.

  • $uid - מזהה משתמש מספרי

  • $gid - מזהה קבוצה ראשית מספרי

  • $quota - מכסת דיסק, או $change / $age בחלק מהמערכות. מחרוזת ריקה כאשר לא־נתמך.

  • $comment - הערה אדמיניסטרטיבית, לעיתים $class. מחרוזת ריקה כאשר לא־נתמך.

  • $gcos - שדה GECOS (בדרך כלל השם האמיתי בתוספת מידע משתמש אחר). tainted תחת -T משום שמשתמשים יכולים לערוך אותו.

  • $dir - ספריית הבית

  • $shell - shell הכניסה. tainted תחת -T.

  • $expire - תפוגת חשבון / סיסמה, כאשר נתמך.

הקשר סקלרי מחזיר רק את $uid. עבור getpwnam - חיפוש לפי שם - הקשר סקלרי מחזיר את ״הדבר האחר,״ בהתאם לכלל ש־upstream מתעד עבור כל הפונקציות getpw* / getgr* / gethost* / getnet* / getproto* / getserv*.

בכישלון חיפוש שני ההקשרים מחזירים את הרשימה הריקה / undef. תמיד יש לבדוק את ההחזרה לפני פירוק.

מצב גלובלי שהוא נוגע בו#

  • מגדיר את $! בכישלון של קריאת מערכת (נדיר - ״משתמש לא נמצא״ אינו כישלון, זוהי החזרה ריקה).

  • תחת -T (מצב taint), $passwd, $gcos, ו־$shell חוזרים tainted. ראו perlsec כיצד לכבס אותם.

  • משתף את אותו מצב איטרטור בסיסי עם getpwent, setpwent, ו־endpwent. קריאה ל־getpwnam אינה מפריעה ללולאת getpwent שנמצאת בעיצומה ב־glibc, אך קוד נייד לא צריך להניח את זה.

דוגמאות#

חיפוש בסיסי של שם־ל־UID בהקשר סקלרי:

my $uid = getpwnam("root");         # 0

רשומה מלאה בהקשר רשימה, עם בדיקה הגנתית:

my @pw = getpwnam($user)
    or die "$user: not in passwd database";
my ($name, undef, $uid, $gid, undef, undef, $gcos, $home, $shell) = @pw;
print "$name ($uid) -> $home, shell $shell\n";

תבנית השמה מ־upstream - פירוק ישיר עם or die:

my ($login, $pass, $uid, $gid) = getpwnam($user)
    or die "$user not in passwd file";

השוואת בעלות קובץ מול משתמש בעל שם ללא אינדוקס שדות שנכתב ביד, דרך עקיפת User::pwent:

use User::pwent;
use File::stat;
my $is_theirs = (stat($filename)->uid == getpwnam($whoever)->uid);

use User::pwent מחליף את getpwnam בגרסה שמחזירה עצם מבורך עם accessors מסוג ->name, ->uid, ->gid, ->dir, ->shell - שימושי כאשר רוצים שדה אחד ואין רצון לספור פסיקים. שתי הצורות אינן מתערבבות: בתוך תחום אחד יש להשתמש או בעקיפה או במובנה, לא בשניהם.

שרשרת fallback עבור ״מי אני רץ בתור״:

my $login = getlogin() || getpwuid($<) || "unknown";

getpwuid הוא המקבילה לפי־UID; getlogin קורא את הרשומה של ה־tty השולט ויכול לשקר על תהליכים מנותקים, כך שזו הבחירה הראשונה, לא היחידה.

מקרי קצה#

  • אין משתמש כזה מחזיר את הרשימה הריקה בהקשר רשימה ו־undef בהקשר סקלרי. זוהי אינה שגיאה - $! אינו מוגדר. יש להבחין בין ״משתמש חסר״ ל־״חיפוש נכשל״ על־ידי בדיקת $! רק כאשר רוצים לדווח על כישלון לא־צפוי, לא כאשר מחליטים האם המשתמש קיים.

  • $passwd שימושי לעיתים נדירות. במערכות Linux ו־BSD מודרניות ה־hash האמיתי נמצא ב־/etc/shadow, ניתן לקריאה רק על־ידי root. כאן מקבלים "x" או "*". יש להשתמש ב־PAM או במודול Authen::PAM לאימות במקום להשוות מול שדה זה.

  • ניידות $quota, $comment, $expire. שדות אלה ריקים או חסרי משמעות ב־Linux. ה־POD של upstream מציג ערכי Config (d_pwquota, d_pwage, d_pwchange, d_pwcomment, d_pwexpire) שניתן לבדוק אם נדרש לדעת בזמן ריצה האם הפלטפורמה ממלאה אותם.

  • שדות tainted תחת -T. $passwd, $gcos, $shell הם tainted מכיוון שמשתמשים יכולים לשנות אותם (דרך chsh, chfn, או עריכות /etc/passwd ישירות בהקשרים מורשים). יש להעביר אותם דרך לכידת regex כדי לכבס לפני שימוש בקריאת מערכת.

  • ערך ההחזרה הוא ״ערך אמת יחיד חסר משמעות״ בהקשר סקלרי בוליאני־למחצה כאשר הרשומה קיימת אך רצית הקשר רשימה. ההחזרה המתועדת בהקשר סקלרי עבור getpwnam היא ה־UID, שעבור root הוא 0 - ערך שקר. if (getpwnam("root")) { ... } לכן נכשל עבור root. יש להשתמש ב־defined או בהקשר רשימה:

    if (defined getpwnam("root"))     { ... }   # correct
    if (my @pw = getpwnam("root"))    { ... }   # also correct
    
  • שם הוא מחרוזת, לא UID. getpwnam(0) ממיר את 0 למחרוזת ומחפש את המשתמש המילולי בשם "0", שכמעט אף פעם אינו קיים. יש להשתמש ב־getpwuid לחיפושים מספריים.

  • directories גדולים (LDAP / NIS / SSSD). getpwnam עובר דרך NSS, כך שהעלות מתרחבת לפי איך שה־resolver המקומי עונה. החמצה מול שרת LDAP שמוגדר באופן שגוי עלולה לחסום למשך שניות. יש לשמור תוצאות בהאש אם מחפשים משתמשים רבים בלולאה הדוקה.

  • Threads. upstream מציין ש־getpwnam_r משמש אוטומטית היכן שהפלטפורמה מספקת אותו; איטרציה של getpwent, בניגוד לכך, נשארת פר־תהליך. לא דאגה תחת pperl (אין ithreads), אך שווה לדעת אם משתפים קוד עם perl5.

הבדלים מ־upstream#

תואם מלא ל־upstream Perl 5.42.

ראו גם#

  • getpwuid - אותה רשומה, נחפשת לפי UID מספרי; יש לשייך עם getpwnam כאשר נדרש ללכת UID ← שם

  • getpwent - לעבור על כל מסד נתוני ה־passwd; יש להשתמש כאשר נדרשים כל המשתמשים, לא ספציפי אחד

  • endpwent - לסגור את האיטרטור של passwd לאחר getpwent

  • getgrnam - מקבילה למסד נתוני הקבוצות; נדרש כדי לפענח את שדה $gid מרשומה זו חזרה לשם קבוצה

  • getlogin - חיפוש זול של ״מי על ה־tty הזה״; יש לסגת ל־getpwnam/getpwuid כאשר הוא מחזיר ריק

  • User::pwent - עטיפת עצם עם accessors נקובי־שם; יש לפנות אליה כאשר רוצים ->uid במקום לספור מיקומי רשימה