• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1'use strict';
2
3const credentials = internalBinding('credentials');
4const rawMethods = internalBinding('process_methods');
5
6process.abort = rawMethods.abort;
7process.umask = wrappedUmask;
8process.chdir = wrappedChdir;
9process.cwd = wrappedCwd;
10
11if (credentials.implementsPosixCredentials) {
12  const wrapped = wrapPosixCredentialSetters(credentials);
13
14  process.initgroups = wrapped.initgroups;
15  process.setgroups = wrapped.setgroups;
16  process.setegid = wrapped.setegid;
17  process.seteuid = wrapped.seteuid;
18  process.setgid = wrapped.setgid;
19  process.setuid = wrapped.setuid;
20}
21
22// ---- keep the attachment of the wrappers above so that it's easier to ----
23// ----              compare the setups side-by-side                    -----
24
25const {
26  parseFileMode,
27  validateArray,
28  validateString,
29} = require('internal/validators');
30
31function wrapPosixCredentialSetters(credentials) {
32  const {
33    codes: {
34      ERR_INVALID_ARG_TYPE,
35      ERR_UNKNOWN_CREDENTIAL,
36    },
37  } = require('internal/errors');
38  const {
39    validateUint32,
40  } = require('internal/validators');
41
42  const {
43    initgroups: _initgroups,
44    setgroups: _setgroups,
45    setegid: _setegid,
46    seteuid: _seteuid,
47    setgid: _setgid,
48    setuid: _setuid,
49  } = credentials;
50
51  function initgroups(user, extraGroup) {
52    validateId(user, 'user');
53    validateId(extraGroup, 'extraGroup');
54    // Result is 0 on success, 1 if user is unknown, 2 if group is unknown.
55    const result = _initgroups(user, extraGroup);
56    if (result === 1) {
57      throw new ERR_UNKNOWN_CREDENTIAL('User', user);
58    } else if (result === 2) {
59      throw new ERR_UNKNOWN_CREDENTIAL('Group', extraGroup);
60    }
61  }
62
63  function setgroups(groups) {
64    validateArray(groups, 'groups');
65    for (let i = 0; i < groups.length; i++) {
66      validateId(groups[i], `groups[${i}]`);
67    }
68    // Result is 0 on success. A positive integer indicates that the
69    // corresponding group was not found.
70    const result = _setgroups(groups);
71    if (result > 0) {
72      throw new ERR_UNKNOWN_CREDENTIAL('Group', groups[result - 1]);
73    }
74  }
75
76  function wrapIdSetter(type, method) {
77    return function(id) {
78      validateId(id, 'id');
79      if (typeof id === 'number') id >>>= 0;
80      // Result is 0 on success, 1 if credential is unknown.
81      const result = method(id);
82      if (result === 1) {
83        throw new ERR_UNKNOWN_CREDENTIAL(type, id);
84      }
85    };
86  }
87
88  function validateId(id, name) {
89    if (typeof id === 'number') {
90      validateUint32(id, name);
91    } else if (typeof id !== 'string') {
92      throw new ERR_INVALID_ARG_TYPE(name, ['number', 'string'], id);
93    }
94  }
95
96  return {
97    initgroups,
98    setgroups,
99    setegid: wrapIdSetter('Group', _setegid),
100    seteuid: wrapIdSetter('User', _seteuid),
101    setgid: wrapIdSetter('Group', _setgid),
102    setuid: wrapIdSetter('User', _setuid),
103  };
104}
105
106// Cache the working directory to prevent lots of lookups. If the working
107// directory is changed by `chdir`, it'll be updated.
108let cachedCwd = '';
109
110function wrappedChdir(directory) {
111  validateString(directory, 'directory');
112  rawMethods.chdir(directory);
113  // Mark cache that it requires an update.
114  cachedCwd = '';
115}
116
117function wrappedUmask(mask) {
118  if (mask !== undefined) {
119    mask = parseFileMode(mask, 'mask');
120  }
121  return rawMethods.umask(mask);
122}
123
124function wrappedCwd() {
125  if (cachedCwd === '')
126    cachedCwd = rawMethods.cwd();
127  return cachedCwd;
128}
129