diff options
Diffstat (limited to 'winsup/cygwin/passwd.cc')
-rw-r--r-- | winsup/cygwin/passwd.cc | 193 |
1 files changed, 115 insertions, 78 deletions
diff --git a/winsup/cygwin/passwd.cc b/winsup/cygwin/passwd.cc index 2f52473c7..22e8b3e20 100644 --- a/winsup/cygwin/passwd.cc +++ b/winsup/cygwin/passwd.cc @@ -1,6 +1,6 @@ /* passwd.cc: getpwnam () and friends - Copyright 1996, 1997, 1998, 2001 Red Hat, Inc. + Copyright 1996, 1997, 1998, 2001, 2002 Red Hat, Inc. This file is part of Cygwin. @@ -18,8 +18,6 @@ details. */ #include "fhandler.h" #include "path.h" #include "dtable.h" -#include "sync.h" -#include "sigproc.h" #include "pinfo.h" #include "cygheap.h" #include <sys/termios.h> @@ -82,19 +80,17 @@ parse_pwd (struct passwd &res, char *buf) /* Allocate enough room for the passwd struct and all the strings in it in one go */ size_t len = strlen (buf); - char *mybuf = (char *) malloc (len + 1); - (void) memcpy (mybuf, buf, len + 1); - if (mybuf[--len] == '\n') - mybuf[len] = '\0'; - - res.pw_name = grab_string (&mybuf); - res.pw_passwd = grab_string (&mybuf); - res.pw_uid = grab_int (&mybuf); - res.pw_gid = grab_int (&mybuf); + if (buf[--len] == '\r') + buf[len] = '\0'; + + res.pw_name = grab_string (&buf); + res.pw_passwd = grab_string (&buf); + res.pw_uid = grab_int (&buf); + res.pw_gid = grab_int (&buf); res.pw_comment = 0; - res.pw_gecos = grab_string (&mybuf); - res.pw_dir = grab_string (&mybuf); - res.pw_shell = grab_string (&mybuf); + res.pw_gecos = grab_string (&buf); + res.pw_dir = grab_string (&buf); + res.pw_shell = grab_string (&buf); } /* Add one line from /etc/passwd into the password cache */ @@ -111,71 +107,102 @@ add_pwd_line (char *line) class passwd_lock { - pthread_mutex_t mutex; + bool armed; + static NO_COPY pthread_mutex_t mutex; public: - passwd_lock (): mutex ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER) {} - void arm () {pthread_mutex_lock (&mutex); } + passwd_lock (bool doit) + { + if (doit) + pthread_mutex_lock (&mutex); + armed = doit; + } ~passwd_lock () { - if (mutex != (pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER) + if (armed) pthread_mutex_unlock (&mutex); } }; +pthread_mutex_t NO_COPY passwd_lock::mutex = (pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER; + /* Read in /etc/passwd and save contents in the password cache. This sets passwd_state to loaded or emulated so functions in this file can tell that /etc/passwd has been read in or will be emulated. */ void read_etc_passwd () { - char linebuf[1024]; - /* A mutex is ok for speed here - pthreads will use critical sections not mutex's - * for non-shared mutexs in the future. Also, this function will at most be called - * once from each thread, after that the passwd_state test will succeed - */ - static NO_COPY passwd_lock here; + static pwdgrp_read pr; - if (cygwin_finished_initializing) - here.arm (); + /* A mutex is ok for speed here - pthreads will use critical sections not + * mutexes for non-shared mutexes in the future. Also, this function will + * at most be called once from each thread, after that the passwd_state + * test will succeed */ + passwd_lock here (cygwin_finished_initializing); - /* if we got blocked by the mutex, then etc_passwd may have been processed */ - if (passwd_state != uninitialized) - return; + /* if we got blocked by the mutex, then etc_passwd may have been processed */ + if (passwd_state != uninitialized) + return; - if (passwd_state != initializing) - { - passwd_state = initializing; - if (max_lines) /* When rereading, free allocated memory first. */ - { - for (int i = 0; i < curr_lines; ++i) - free (passwd_buf[i].pw_name); - curr_lines = 0; - } - - FILE *f = fopen ("/etc/passwd", "rt"); - - if (f) - { - while (fgets (linebuf, sizeof (linebuf), f) != NULL) - { - if (strlen (linebuf)) - add_pwd_line (linebuf); - } - - passwd_state.set_last_modified (f); - fclose (f); - passwd_state = loaded; - } - else - { - debug_printf ("Emulating /etc/passwd"); - snprintf (linebuf, sizeof (linebuf), "%s::%u:%u::%s:/bin/sh", cygheap->user.name (), - DEFAULT_UID, DEFAULT_GID, getenv ("HOME") ?: "/"); - add_pwd_line (linebuf); - passwd_state = emulated; - } + if (passwd_state != initializing) + { + passwd_state = initializing; + if (pr.open ("/etc/passwd")) + { + char *line; + while ((line = pr.gets ()) != NULL) + if (strlen (line)) + add_pwd_line (line); + + passwd_state.set_last_modified (pr.get_fhandle (), pr.get_fname ()); + passwd_state = loaded; + pr.close (); + debug_printf ("Read /etc/passwd, %d lines", curr_lines); + } + else + { + static char linebuf[1024]; + + if (wincap.has_security ()) + { + HANDLE ptok; + cygsid tu, tg; + DWORD siz; + + if (OpenProcessToken (hMainProc, TOKEN_QUERY, &ptok)) + { + if (GetTokenInformation (ptok, TokenUser, &tu, sizeof tu, + &siz) + && GetTokenInformation (ptok, TokenPrimaryGroup, &tg, + sizeof tg, &siz)) + { + char strbuf[100]; + snprintf (linebuf, sizeof (linebuf), + "%s::%lu:%lu:%s:%s:/bin/sh", + cygheap->user.name (), + *GetSidSubAuthority (tu, + *GetSidSubAuthorityCount(tu) - 1), + *GetSidSubAuthority (tg, + *GetSidSubAuthorityCount(tg) - 1), + tu.string (strbuf), getenv ("HOME") ?: "/"); + debug_printf ("Emulating /etc/passwd: %s", linebuf); + add_pwd_line (linebuf); + passwd_state = emulated; + } + CloseHandle (ptok); + } + } + if (passwd_state != emulated) + { + snprintf (linebuf, sizeof (linebuf), "%s::%u:%u::%s:/bin/sh", + cygheap->user.name (), (unsigned) DEFAULT_UID, + (unsigned) DEFAULT_GID, getenv ("HOME") ?: "/"); + debug_printf ("Emulating /etc/passwd: %s", linebuf); + add_pwd_line (linebuf); + passwd_state = emulated; + } + } - } + } return; } @@ -183,7 +210,7 @@ read_etc_passwd () /* Cygwin internal */ /* If this ever becomes non-reentrant, update all the getpw*_r functions */ static struct passwd * -search_for (uid_t uid, const char *name) +search_for (__uid32_t uid, const char *name) { struct passwd *res = 0; struct passwd *default_pw = 0; @@ -199,7 +226,7 @@ search_for (uid_t uid, const char *name) if (strcasematch (name, res->pw_name)) return res; } - else if (uid == res->pw_uid) + else if (uid == (__uid32_t) res->pw_uid) return res; } @@ -214,18 +241,24 @@ search_for (uid_t uid, const char *name) } extern "C" struct passwd * -getpwuid (uid_t uid) +getpwuid32 (__uid32_t uid) { if (passwd_state <= initializing) read_etc_passwd (); - pthread_testcancel(); + pthread_testcancel (); return search_for (uid, 0); } +extern "C" struct passwd * +getpwuid (__uid16_t uid) +{ + return getpwuid32 (uid16touid32 (uid)); +} + extern "C" int -getpwuid_r (uid_t uid, struct passwd *pwd, char *buffer, size_t bufsize, struct passwd **result) +getpwuid_r32 (__uid32_t uid, struct passwd *pwd, char *buffer, size_t bufsize, struct passwd **result) { *result = NULL; @@ -235,7 +268,7 @@ getpwuid_r (uid_t uid, struct passwd *pwd, char *buffer, size_t bufsize, struct if (passwd_state <= initializing) read_etc_passwd (); - pthread_testcancel(); + pthread_testcancel (); struct passwd *temppw = search_for (uid, 0); @@ -266,13 +299,19 @@ getpwuid_r (uid_t uid, struct passwd *pwd, char *buffer, size_t bufsize, struct return 0; } +extern "C" int +getpwuid_r (__uid16_t uid, struct passwd *pwd, char *buffer, size_t bufsize, struct passwd **result) +{ + return getpwuid_r32 (uid16touid32 (uid), pwd, buffer, bufsize, result); +} + extern "C" struct passwd * getpwnam (const char *name) { if (passwd_state <= initializing) read_etc_passwd (); - pthread_testcancel(); + pthread_testcancel (); return search_for (0, name); } @@ -293,7 +332,7 @@ getpwnam_r (const char *nam, struct passwd *pwd, char *buffer, size_t bufsize, s if (passwd_state <= initializing) read_etc_passwd (); - pthread_testcancel(); + pthread_testcancel (); struct passwd *temppw = search_for (0, nam); @@ -337,7 +376,7 @@ getpwent (void) } extern "C" struct passwd * -getpwduid (uid_t) +getpwduid (__uid16_t) { return NULL; } @@ -385,14 +424,12 @@ getpass (const char * prompt) if (passwd_state <= initializing) read_etc_passwd (); - if (cygheap->fdtab.not_open (0)) - { - set_errno (EBADF); - pass[0] = '\0'; - } + cygheap_fdget fhstdin (0); + + if (fhstdin < 0) + pass[0] = '\0'; else { - fhandler_base *fhstdin = cygheap->fdtab[0]; fhstdin->tcgetattr (&ti); newti = ti; newti.c_lflag &= ~ECHO; |