📄 syscalls.cc
字号:
debug_printf ("uid: %d myself->gid: %d", uid, myself->gid); if (!wincap.has_security () || (uid == myself->uid && !cygheap->user.groups.ischanged)) { debug_printf ("Nothing happens"); return 0; } if (uid == ILLEGAL_UID) { set_errno (EINVAL); return -1; } sigframe thisframe (mainthread); cygsid usersid; user_groups &groups = cygheap->user.groups; HANDLE ptok, sav_token; BOOL sav_impersonated, sav_token_is_internal_token; BOOL process_ok, explicitly_created_token = FALSE; struct passwd * pw_new; PSID origpsid, psid2 = NO_SID; pw_new = getpwuid32 (uid); if (!usersid.getfrompw (pw_new)) { set_errno (EINVAL); return -1; } /* Save current information */ sav_token = cygheap->user.token; sav_impersonated = cygheap->user.impersonated; RevertToSelf (); if (!OpenProcessToken (hMainProc, TOKEN_QUERY | TOKEN_ADJUST_DEFAULT, &ptok)) { __seterrno (); goto failed; } /* Verify if the process token is suitable. Currently we do not try to differentiate between internal tokens and others */ process_ok = verify_token (ptok, usersid, groups); debug_printf ("Process token %sverified", process_ok ? "" : "not "); if (process_ok) { if (cygheap->user.issetuid ()) cygheap->user.impersonated = FALSE; else { CloseHandle (ptok); goto success; /* No change */ } } if (!process_ok && cygheap->user.token != INVALID_HANDLE_VALUE) { /* Verify if the current tokem is suitable */ BOOL token_ok = verify_token (cygheap->user.token, usersid, groups, &sav_token_is_internal_token); debug_printf ("Thread token %d %sverified", cygheap->user.token, token_ok?"":"not "); if (!token_ok) cygheap->user.token = INVALID_HANDLE_VALUE; else { /* Return if current token is valid */ if (cygheap->user.impersonated) { CloseHandle (ptok); if (!ImpersonateLoggedOnUser (cygheap->user.token)) system_printf ("Impersonating in seteuid failed: %E"); goto success; /* No change */ } } } /* Set process def dacl to allow access to impersonated token */ char dacl_buf[MAX_DACL_LEN (5)]; if (usersid != (origpsid = cygheap->user.orig_sid ())) psid2 = usersid; if (sec_acl ((PACL) dacl_buf, FALSE, origpsid, psid2)) { TOKEN_DEFAULT_DACL tdacl; tdacl.DefaultDacl = (PACL) dacl_buf; if (!SetTokenInformation (ptok, TokenDefaultDacl, &tdacl, sizeof dacl_buf)) debug_printf ("SetTokenInformation" "(TokenDefaultDacl): %E"); } CloseHandle (ptok); if (!process_ok && cygheap->user.token == INVALID_HANDLE_VALUE) { /* If no impersonation token is available, try to authenticate using NtCreateToken () or subauthentication. */ cygheap->user.token = create_token (usersid, groups, pw_new); if (cygheap->user.token != INVALID_HANDLE_VALUE) explicitly_created_token = TRUE; else { /* create_token failed. Try subauthentication. */ debug_printf ("create token failed, try subauthentication."); cygheap->user.token = subauth (pw_new); if (cygheap->user.token == INVALID_HANDLE_VALUE) goto failed; } } /* If using the token, set info and impersonate */ if (!process_ok) { /* If the token was explicitly created, all information has already been set correctly. */ if (!explicitly_created_token) { /* Try setting owner to same value as user. */ if (!SetTokenInformation (cygheap->user.token, TokenOwner, &usersid, sizeof usersid)) debug_printf ("SetTokenInformation(user.token, " "TokenOwner): %E"); /* Try setting primary group in token to current group */ if (!SetTokenInformation (cygheap->user.token, TokenPrimaryGroup, &groups.pgsid, sizeof (cygsid))) debug_printf ("SetTokenInformation(user.token, " "TokenPrimaryGroup): %E"); } /* Now try to impersonate. */ if (!ImpersonateLoggedOnUser (cygheap->user.token)) { debug_printf ("ImpersonateLoggedOnUser %E"); __seterrno (); goto failed; } cygheap->user.impersonated = TRUE; } /* If sav_token was internally created and is replaced, destroy it. */ if (sav_token != INVALID_HANDLE_VALUE && sav_token != cygheap->user.token && sav_token_is_internal_token) CloseHandle (sav_token); cygheap->user.set_name (pw_new->pw_name); cygheap->user.set_sid (usersid);success: myself->uid = uid; groups.ischanged = FALSE; return 0; failed: cygheap->user.token = sav_token; cygheap->user.impersonated = sav_impersonated; if (cygheap->user.issetuid () && !ImpersonateLoggedOnUser (cygheap->user.token)) system_printf ("Impersonating in seteuid failed: %E"); return -1;}extern "C" intseteuid (__uid16_t uid){ return seteuid32 (uid16touid32 (uid));}/* setuid: POSIX 4.2.2.1 */extern "C" intsetuid32 (__uid32_t uid){ int ret = seteuid32 (uid); if (!ret) cygheap->user.real_uid = myself->uid; debug_printf ("real: %d, effective: %d", cygheap->user.real_uid, myself->uid); return ret;}extern "C" intsetuid (__uid16_t uid){ return setuid32 (uid16touid32 (uid));}/* setegid: from System V. */extern "C" intsetegid32 (__gid32_t gid){ if (!wincap.has_security () || gid == myself->gid) return 0; if (gid == ILLEGAL_GID) { set_errno (EINVAL); return -1; } sigframe thisframe (mainthread); user_groups * groups = &cygheap->user.groups; cygsid gsid; HANDLE ptok; struct __group32 * gr = getgrgid32 (gid); if (!gr || gr->gr_gid != gid || !gsid.getfromgr (gr)) { set_errno (EINVAL); return -1; } myself->gid = gid; groups->update_pgrp (gsid); /* If impersonated, update primary group and revert */ if (cygheap->user.issetuid ()) { if (!SetTokenInformation (cygheap->user.token, TokenPrimaryGroup, &gsid, sizeof gsid)) debug_printf ("SetTokenInformation(thread, " "TokenPrimaryGroup): %E"); RevertToSelf (); } if (!OpenProcessToken (hMainProc, TOKEN_ADJUST_DEFAULT, &ptok)) debug_printf ("OpenProcessToken(): %E"); else { if (!SetTokenInformation (ptok, TokenPrimaryGroup, &gsid, sizeof gsid)) debug_printf ("SetTokenInformation(process, " "TokenPrimaryGroup): %E"); CloseHandle (ptok); } if (cygheap->user.issetuid () && !ImpersonateLoggedOnUser (cygheap->user.token)) system_printf ("Impersonating in setegid failed: %E"); return 0;}extern "C" intsetegid (__gid16_t gid){ return setegid32 (gid16togid32 (gid));}/* setgid: POSIX 4.2.2.1 */extern "C" intsetgid32 (__gid32_t gid){ int ret = setegid32 (gid); if (!ret) cygheap->user.real_gid = myself->gid; return ret;}extern "C" intsetgid (__gid16_t gid){ int ret = setegid32 (gid16togid32 (gid)); if (!ret) cygheap->user.real_gid = myself->gid; return ret;}/* chroot: privileged Unix system call. *//* FIXME: Not privileged here. How should this be done? */extern "C" intchroot (const char *newroot){ sigframe thisframe (mainthread); path_conv path (newroot, PC_SYM_FOLLOW | PC_FULL | PC_POSIX); int ret; if (path.error) ret = -1; else if (!path.exists ()) { set_errno (ENOENT); ret = -1; } else if (!path.isdir ()) { set_errno (ENOTDIR); ret = -1; } else { cygheap->root.set (path.normalized_path, path); ret = 0; } syscall_printf ("%d = chroot (%s)", ret ? get_errno () : 0, newroot ? newroot : "NULL"); return ret;}extern "C" intcreat (const char *path, mode_t mode){ sigframe thisframe (mainthread); return open (path, O_WRONLY | O_CREAT | O_TRUNC, mode);}extern "C" void__assertfail (){ exit (99);}extern "C" intgetw (FILE *fp){ sigframe thisframe (mainthread); int w, ret; ret = fread (&w, sizeof (int), 1, fp); return ret != 1 ? EOF : w;}extern "C" intputw (int w, FILE *fp){ sigframe thisframe (mainthread); int ret; ret = fwrite (&w, sizeof (int), 1, fp); if (feof (fp) || ferror (fp)) return -1; return 0;}extern "C" intwcscmp (const wchar_t *s1, const wchar_t *s2){ while (*s1 && *s1 == *s2) { s1++; s2++; } return (* (unsigned short *) s1) - (* (unsigned short *) s2);}extern "C" size_twcslen (const wchar_t *s1){ int l = 0; while (s1[l]) l++; return l;}/* FIXME: to do this right, maybe work out the usoft va_list machine and use wsvprintfW instead?*/extern "C" intwprintf (const char *fmt, ...){ va_list ap; int ret; va_start (ap, fmt); ret = vprintf (fmt, ap); va_end (ap); return ret;}extern "C" intvhangup (){ set_errno (ENOSYS); return -1;}extern "C" _PTRmemccpy (_PTR out, const _PTR in, int c, size_t len){ const char *inc = (char *) in; char *outc = (char *) out; while (len) { char x = *inc++; *outc++ = x; if (x == c) return outc; len --; } return 0;}extern "C" intnice (int incr){ sigframe thisframe (mainthread); DWORD priority[] = { IDLE_PRIORITY_CLASS, IDLE_PRIORITY_CLASS, NORMAL_PRIORITY_CLASS, HIGH_PRIORITY_CLASS, REALTIME_PRIORITY_CLASS, REALTIME_PRIORITY_CLASS }; int curr = 2; switch (GetPriorityClass (hMainProc)) { case IDLE_PRIORITY_CLASS: curr = 1; break; case NORMAL_PRIORITY_CLASS: curr = 2; break; case HIGH_PRIORITY_CLASS: curr = 3; break; case REALTIME_PRIORITY_CLASS: curr = 4; break; } if (incr > 0) incr = -1; else if (incr < 0) incr = 1; if (SetPriorityClass (hMainProc, priority[curr + incr]) == FALSE) { __seterrno (); return -1; } return 0;}/* * Find the first bit set in I. */extern "C" intffs (int i){ static const unsigned char table[] = { 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 }; unsigned long int a; unsigned long int x = i & -i; a = x <= 0xffff ? (x <= 0xff ? 0 : 8) : (x <= 0xffffff ? 16 : 24); return table[x >> a] + a;}extern "C" voidlogin (struct utmp *ut){ sigframe thisframe (mainthread); register int fd; pututline (ut); if ((fd = open (_PATH_WTMP, O_WRONLY | O_APPEND | O_BINARY, 0)) >= 0) { (void) write (fd, (char *) ut, sizeof (struct utmp)); (void) close (fd); }}/* It isn't possible to use unix-style I/O function in logout code becausecygwin's I/O subsystem may be inaccessible at logout () call time.FIXME (cgf): huh?*/extern "C" intlogout (char *line){ sigframe thisframe (mainthread); int res = 0; HANDLE ut_fd; static const char path_utmp[] = _PATH_UTMP; path_conv win32_path (path_utmp); if (win32_path.error) return 0; ut_fd = CreateFile (win32_path.get_win32 (), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, &sec_none_nih, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (ut_fd != INVALID_HANDLE_VALUE) { struct utmp *ut; struct utmp ut_buf[100]; /* FIXME: utmp file access is not 64 bit clean for now. */ __off32_t pos = 0; /* Position in file */ DWORD rd; while (!res && ReadFile (ut_fd, ut_buf, sizeof ut_buf, &rd, NULL) && rd != 0) { struct utmp *ut_end = (struct utmp *) ((char *) ut_buf + rd); for (ut = ut_buf; ut < ut_end; ut++, pos += sizeof (*ut)) if (ut->ut_name[0] && strncmp (ut->ut_line, line, sizeof (ut->ut_line)) == 0) /* Found the entry for LINE; mark it as logged out. */ { /* Zero out entries describing who's logged in. */ bzero (ut->ut_name, sizeof (ut->ut_name)); bzero (ut->ut_host, sizeof (ut->ut_host)); time (&ut->ut_time); /* Now seek back to the position in utmp at which UT occured, and write the new version of UT there. */ if ((SetFilePointer (ut_fd, pos, 0, FILE_BEGIN) != 0xFFFFFFFF) && (WriteFile (ut_fd, (char *) ut, sizeof (*ut), &rd, NULL))) { res = 1; break; } } } CloseHandle (ut_fd); } return res;}static int utmp_fd = -2;static char *utmp_file = (char *) _PATH_UTMP;static struct utmp utmp_data;extern "C" voidsetutent (){ sigframe thisframe (mainthread); if (utmp_fd == -2) { utmp_fd = open (utmp_file, O_RDWR); } lseek (utmp_fd, 0, SEEK_SET);}extern "C" voidendutent (){ sigframe thisframe (mainthread); if (utmp_fd != -2) { close (utmp_fd); utmp_fd = -2; }}extern "C" voidutmpname (_CONST char *file){ sigframe thisframe (mainthread); if (check_null_empty_str (file)) { debug_printf ("Invalid file"); return; } endutent (); utmp_file = strdup (file); debug_printf ("New UTMP file: %s", utmp_file);}extern "C" struct utmp *getutent (){ sigframe thisframe (mainthread); if (utmp_fd == -2) setutent (); if (read (utmp_fd, &utmp_data, sizeof (utmp_data)) != sizeof (utmp_data)) return NULL; return &utmp_data;}extern "C" struct utmp *getutid (struct utmp *id){ sigframe thisframe (mainthread); if (check_null_invalid_struct_errno (id)) return NULL; while (read (utmp_fd, &utmp_data, sizeof (utmp_data)) == sizeof (utmp_data)) { switch (id->ut_type) { case RUN_LVL: case BOOT_TIME: case OLD_TIME: case NEW_TIME: if (id->ut_type == utmp_data.ut_type) return &utmp_data; break; case INIT_PROCESS: case LOGIN_PROCESS: case USER_PROCESS: case DEAD_PROCESS: if (strncmp (id->ut_id, utmp_data.ut_id, UT_IDLEN) == 0) return &utmp_data; break; default: return NULL; } } return NULL;}extern "C" struct utmp *getutline (struct utmp *line){ sigframe thisframe (mainthread); if (check_null_invalid_struct_errno (line)) return NULL; while (read (utmp_fd, &utmp_data, sizeof (utmp_data)) == sizeof (utmp_data)) { if ((utmp_data.ut_type == LOGIN_PROCESS || utmp_data.ut_type == USER_PROCESS) && !strncmp (utmp_data.ut_line, line->ut_line, sizeof (utmp_data.ut_line))) return &utmp_data; } return NULL;}extern "C" voidpututline (struct utmp *ut){ sigframe thisframe (mainthread); if (check_null_invalid_struct (ut)) return; setutent (); struct utmp *u; if ((u = getutid (ut))) lseek (utmp_fd, -sizeof(struct utmp), SEEK_CUR); else lseek (utmp_fd, 0, SEEK_END); (void) write (utmp_fd, (char *) ut, sizeof (struct utmp));}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -