1// Copyright Joyent, Inc. and other Node contributors.
2//
3// Permission is hereby granted, free of charge, to any person obtaining a
4// copy of this software and associated documentation files (the
5// "Software"), to deal in the Software without restriction, including
6// without limitation the rights to use, copy, modify, merge, publish,
7// distribute, sublicense, and/or sell copies of the Software, and to permit
8// persons to whom the Software is furnished to do so, subject to the
9// following conditions:
10//
11// The above copyright notice and this permission notice shall be included
12// in all copies or substantial portions of the Software.
13//
14// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20// USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22'use strict';
23const common = require('../common');
24
25const assert = require('assert');
26
27if (common.isWindows) {
28  // uid/gid functions are POSIX only.
29  assert.strictEqual(process.getuid, undefined);
30  assert.strictEqual(process.getgid, undefined);
31  assert.strictEqual(process.setuid, undefined);
32  assert.strictEqual(process.setgid, undefined);
33  return;
34}
35
36if (!common.isMainThread)
37  return;
38
39assert.throws(() => {
40  process.setuid({});
41}, {
42  code: 'ERR_INVALID_ARG_TYPE',
43  message: 'The "id" argument must be one of type ' +
44    'number or string. Received an instance of Object'
45});
46
47assert.throws(() => {
48  process.setuid('fhqwhgadshgnsdhjsdbkhsdabkfabkveyb');
49}, {
50  code: 'ERR_UNKNOWN_CREDENTIAL',
51  message: 'User identifier does not exist: fhqwhgadshgnsdhjsdbkhsdabkfabkveyb'
52});
53
54// Passing -0 shouldn't crash the process
55// Refs: https://github.com/nodejs/node/issues/32750
56// And neither should values exceeding 2 ** 31 - 1.
57for (const id of [-0, 2 ** 31, 2 ** 32 - 1]) {
58  for (const fn of [process.setuid, process.setuid, process.setgid, process.setegid]) {
59    try { fn(id); } catch {
60      // Continue regardless of error.
61    }
62  }
63}
64
65// If we're not running as super user...
66if (process.getuid() !== 0) {
67  // Should not throw.
68  process.getgid();
69  process.getuid();
70
71  assert.throws(
72    () => { process.setgid('nobody'); },
73    /(?:EPERM, .+|Group identifier does not exist: nobody)$/
74  );
75
76  assert.throws(
77    () => { process.setuid('nobody'); },
78    /(?:EPERM, .+|User identifier does not exist: nobody)$/
79  );
80  return;
81}
82
83// If we are running as super user...
84const oldgid = process.getgid();
85try {
86  process.setgid('nobody');
87} catch (err) {
88  if (err.code !== 'ERR_UNKNOWN_CREDENTIAL') {
89    throw err;
90  }
91  process.setgid('nogroup');
92}
93
94const newgid = process.getgid();
95assert.notStrictEqual(newgid, oldgid);
96
97const olduid = process.getuid();
98process.setuid('nobody');
99const newuid = process.getuid();
100assert.notStrictEqual(newuid, olduid);
101