• 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  validateString
28} = require('internal/validators');
29
30function wrapPosixCredentialSetters(credentials) {
31  const {
32    ArrayIsArray,
33  } = primordials;
34  const {
35    codes: {
36      ERR_INVALID_ARG_TYPE,
37      ERR_UNKNOWN_CREDENTIAL
38    }
39  } = require('internal/errors');
40  const {
41    validateUint32
42  } = require('internal/validators');
43
44  const {
45    initgroups: _initgroups,
46    setgroups: _setgroups,
47    setegid: _setegid,
48    seteuid: _seteuid,
49    setgid: _setgid,
50    setuid: _setuid
51  } = credentials;
52
53  function initgroups(user, extraGroup) {
54    validateId(user, 'user');
55    validateId(extraGroup, 'extraGroup');
56    // Result is 0 on success, 1 if user is unknown, 2 if group is unknown.
57    const result = _initgroups(user, extraGroup);
58    if (result === 1) {
59      throw new ERR_UNKNOWN_CREDENTIAL('User', user);
60    } else if (result === 2) {
61      throw new ERR_UNKNOWN_CREDENTIAL('Group', extraGroup);
62    }
63  }
64
65  function setgroups(groups) {
66    if (!ArrayIsArray(groups)) {
67      throw new ERR_INVALID_ARG_TYPE('groups', 'Array', groups);
68    }
69    for (let i = 0; i < groups.length; i++) {
70      validateId(groups[i], `groups[${i}]`);
71    }
72    // Result is 0 on success. A positive integer indicates that the
73    // corresponding group was not found.
74    const result = _setgroups(groups);
75    if (result > 0) {
76      throw new ERR_UNKNOWN_CREDENTIAL('Group', groups[result - 1]);
77    }
78  }
79
80  function wrapIdSetter(type, method) {
81    return function(id) {
82      validateId(id, 'id');
83      if (typeof id === 'number') id |= 0;
84      // Result is 0 on success, 1 if credential is unknown.
85      const result = method(id);
86      if (result === 1) {
87        throw new ERR_UNKNOWN_CREDENTIAL(type, id);
88      }
89    };
90  }
91
92  function validateId(id, name) {
93    if (typeof id === 'number') {
94      validateUint32(id, name);
95    } else if (typeof id !== 'string') {
96      throw new ERR_INVALID_ARG_TYPE(name, ['number', 'string'], id);
97    }
98  }
99
100  return {
101    initgroups,
102    setgroups,
103    setegid: wrapIdSetter('Group', _setegid),
104    seteuid: wrapIdSetter('User', _seteuid),
105    setgid: wrapIdSetter('Group', _setgid),
106    setuid: wrapIdSetter('User', _setuid)
107  };
108}
109
110// Cache the working directory to prevent lots of lookups. If the working
111// directory is changed by `chdir`, it'll be updated.
112let cachedCwd = '';
113
114function wrappedChdir(directory) {
115  validateString(directory, 'directory');
116  rawMethods.chdir(directory);
117  // Mark cache that it requires an update.
118  cachedCwd = '';
119}
120
121function wrappedUmask(mask) {
122  if (mask !== undefined) {
123    mask = parseFileMode(mask, 'mask');
124  }
125  return rawMethods.umask(mask);
126}
127
128function wrappedCwd() {
129  if (cachedCwd === '')
130    cachedCwd = rawMethods.cwd();
131  return cachedCwd;
132}
133