mirror of https://github.com/nodejs/node.git
Allow process.setuid() and process.setgid() to accept string names in lieu of numeric IDs
parent
2663c69f8d
commit
2420f07e94
54
src/node.cc
54
src/node.cc
|
@ -14,6 +14,8 @@
|
|||
#include <dlfcn.h> /* dlopen(), dlsym() */
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h> /* setuid, getuid */
|
||||
#include <pwd.h> /* getpwnam() */
|
||||
#include <grp.h> /* getgrnam() */
|
||||
|
||||
#include <node_buffer.h>
|
||||
#include <node_io_watcher.h>
|
||||
|
@ -90,6 +92,10 @@ static ev_async eio_want_poll_notifier;
|
|||
static ev_async eio_done_poll_notifier;
|
||||
static ev_idle eio_poller;
|
||||
|
||||
// Buffer for getpwnam_r(), getgrpam_r(); keep this scoped at file-level rather
|
||||
// than method-level to avoid excess stack usage.
|
||||
static char getbuf[1024];
|
||||
|
||||
// We need to notify V8 when we're idle so that it can run the garbage
|
||||
// collector. The interface to this is V8::IdleNotification(). It returns
|
||||
// true if the heap hasn't be fully compacted, and needs to be run again.
|
||||
|
@ -1152,11 +1158,29 @@ static Handle<Value> SetGid(const Arguments& args) {
|
|||
String::New("setgid requires 1 argument")));
|
||||
}
|
||||
|
||||
Local<Integer> given_gid = args[0]->ToInteger();
|
||||
int gid = given_gid->Int32Value();
|
||||
int gid;
|
||||
|
||||
if (args[0]->IsNumber()) {
|
||||
gid = args[0]->Int32Value();
|
||||
} else if (args[0]->IsString()) {
|
||||
String::Utf8Value grpnam(args[0]->ToString());
|
||||
struct group grp, *grpp = NULL;
|
||||
int err;
|
||||
|
||||
if ((err = getgrnam_r(*grpnam, &grp, getbuf, sizeof(getbuf), &grpp)) ||
|
||||
grpp == NULL) {
|
||||
return ThrowException(ErrnoException(errno, "getgrnam_r"));
|
||||
}
|
||||
|
||||
gid = grpp->gr_gid;
|
||||
} else {
|
||||
return ThrowException(Exception::Error(
|
||||
String::New("setgid argument must be a number or a string")));
|
||||
}
|
||||
|
||||
int result;
|
||||
if ((result = setgid(gid)) != 0) {
|
||||
return ThrowException(Exception::Error(String::New(strerror(errno))));
|
||||
return ThrowException(ErrnoException(errno, "setgid"));
|
||||
}
|
||||
return Undefined();
|
||||
}
|
||||
|
@ -1169,11 +1193,29 @@ static Handle<Value> SetUid(const Arguments& args) {
|
|||
String::New("setuid requires 1 argument")));
|
||||
}
|
||||
|
||||
Local<Integer> given_uid = args[0]->ToInteger();
|
||||
int uid = given_uid->Int32Value();
|
||||
int uid;
|
||||
|
||||
if (args[0]->IsNumber()) {
|
||||
uid = args[0]->Int32Value();
|
||||
} else if (args[0]->IsString()) {
|
||||
String::Utf8Value pwnam(args[0]->ToString());
|
||||
struct passwd pwd, *pwdp = NULL;
|
||||
int err;
|
||||
|
||||
if ((err = getpwnam_r(*pwnam, &pwd, getbuf, sizeof(getbuf), &pwdp)) ||
|
||||
pwdp == NULL) {
|
||||
return ThrowException(ErrnoException(errno, "getpwnam_r"));
|
||||
}
|
||||
|
||||
uid = pwdp->pw_uid;
|
||||
} else {
|
||||
return ThrowException(Exception::Error(
|
||||
String::New("setuid argument must be a number or a string")));
|
||||
}
|
||||
|
||||
int result;
|
||||
if ((result = setuid(uid)) != 0) {
|
||||
return ThrowException(Exception::Error(String::New(strerror(errno))));
|
||||
return ThrowException(ErrnoException(errno, "setuid"));
|
||||
}
|
||||
return Undefined();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
// Requires special privlages
|
||||
require('../common');
|
||||
var assert = require('assert');
|
||||
|
||||
var oldgid = process.getgid();
|
||||
process.setgid('nobody');
|
||||
var newgid = process.getgid();
|
||||
assert.notEqual(newgid, oldgid, 'gids expected to be different');
|
||||
|
||||
var olduid = process.getuid();
|
||||
process.setuid('nobody');
|
||||
var newuid = process.getuid();
|
||||
assert.notEqual(newuid, olduid, 'uids expected to be different');
|
||||
|
||||
try {
|
||||
process.setuid('nobody1234');
|
||||
} catch (e) {
|
||||
assert.equal(
|
||||
e.message,
|
||||
'failed to resolve group',
|
||||
'unexpected error message'
|
||||
);
|
||||
}
|
Loading…
Reference in New Issue