Move common DOS utility helper code into tools.c and expose it through net.h. This removes duplicated command-local helpers from GRANT, RIGHTS, FLAG, FLAGDIR and the trustee helper layer. The shared helpers cover case-insensitive argument comparison, help and option detection, /FILES and /SUBDIRS parsing, current network directory handle lookup, current volume prefix formatting, uppercase DOS path copying, basename/header-path handling, wildcard detection and simple path joining/splitting. Keep the command frontends smaller and less coupled so the current multicall utility can later be split into smaller grouped multicall binaries, such as trustee tools, login/session tools and file/flag tools. Update the DOS utilities README for the newer Client32 and trustee commands. Document RIGHTS, GRANT, REVOKE and REMOVE in the status, feature, command and install sections. Add command reference entries for the trustee tools, including Novell-style syntax, supported rights, recursive/file options and missing-trustee behavior. Also mention the shared trustee helper layer and common tools.c helpers used by the newer command frontends.
346 lines
8.5 KiB
C
346 lines
8.5 KiB
C
/* grant.c - Novell GRANT-like DOS utility, first Client32 implementation */
|
|
|
|
#include "net.h"
|
|
#include "c32ncp.h"
|
|
|
|
#define GRANT_BINDERY_USER 0x0001
|
|
#define GRANT_BINDERY_GROUP 0x0002
|
|
|
|
#define NCP_RIGHT_READ 0x0001
|
|
#define NCP_RIGHT_WRITE 0x0002
|
|
#define NCP_RIGHT_OPEN 0x0004
|
|
#define NCP_RIGHT_CREATE 0x0008
|
|
#define NCP_RIGHT_DELETE 0x0010
|
|
#define NCP_RIGHT_OWNER 0x0020
|
|
#define NCP_RIGHT_SEARCH 0x0040
|
|
#define NCP_RIGHT_MODIFY 0x0080
|
|
#define NCP_RIGHT_SUPER 0x0100
|
|
|
|
/* Novell GRANT ALL assigns all normal trustee rights, not Supervisor. */
|
|
#define NCP_RIGHT_ALL_386 (NCP_RIGHT_READ | NCP_RIGHT_WRITE | \
|
|
NCP_RIGHT_CREATE | NCP_RIGHT_DELETE | \
|
|
NCP_RIGHT_MODIFY | NCP_RIGHT_SEARCH | \
|
|
NCP_RIGHT_OWNER)
|
|
|
|
static void grant_usage_error(void)
|
|
{
|
|
fprintf(stdout, "Command line arguments violate grammar defined for GRANT.\n\n");
|
|
}
|
|
|
|
static void grant_usage(void)
|
|
{
|
|
fprintf(stdout, "Usage: GRANT rightslist* [FOR path] TO [USER | GROUP] name [options]\n");
|
|
fprintf(stdout, "Options: /SubDirectories | /Files\n\n");
|
|
fprintf(stdout, "386 Rights:\n");
|
|
fprintf(stdout, "--------------------\n");
|
|
fprintf(stdout, "ALL = All\n");
|
|
fprintf(stdout, "N = No Rights\n");
|
|
fprintf(stdout, "S = Supervisor\n");
|
|
fprintf(stdout, "R = Read\n");
|
|
fprintf(stdout, "W = Write\n");
|
|
fprintf(stdout, "C = Create\n");
|
|
fprintf(stdout, "E = Erase\n");
|
|
fprintf(stdout, "M = Modify\n");
|
|
fprintf(stdout, "F = File Scan\n");
|
|
fprintf(stdout, "A = Access Control\n");
|
|
}
|
|
|
|
static void grant_rights_bracket(uint16 rights, char *out)
|
|
{
|
|
out[0] = (rights & NCP_RIGHT_SUPER) ? 'S' : ' ';
|
|
out[1] = (rights & NCP_RIGHT_READ) ? 'R' : ' ';
|
|
out[2] = (rights & NCP_RIGHT_WRITE) ? 'W' : ' ';
|
|
out[3] = (rights & NCP_RIGHT_CREATE) ? 'C' : ' ';
|
|
out[4] = (rights & NCP_RIGHT_DELETE) ? 'E' : ' ';
|
|
out[5] = (rights & NCP_RIGHT_MODIFY) ? 'M' : ' ';
|
|
out[6] = (rights & NCP_RIGHT_SEARCH) ? 'F' : ' ';
|
|
out[7] = (rights & NCP_RIGHT_OWNER) ? 'A' : ' ';
|
|
out[8] = '\0';
|
|
}
|
|
|
|
|
|
static void grant_rights_string(uint16 rights, char *out)
|
|
{
|
|
char *p = out;
|
|
|
|
if (rights == 0) {
|
|
strcpy(out, "N");
|
|
return;
|
|
}
|
|
|
|
if ((rights & NCP_RIGHT_ALL_386) == NCP_RIGHT_ALL_386) {
|
|
strcpy(out, "ALL");
|
|
return;
|
|
}
|
|
|
|
if (rights & NCP_RIGHT_SUPER) *p++ = 'S';
|
|
if (rights & NCP_RIGHT_READ) *p++ = 'R';
|
|
if (rights & NCP_RIGHT_WRITE) *p++ = 'W';
|
|
if (rights & NCP_RIGHT_CREATE) *p++ = 'C';
|
|
if (rights & NCP_RIGHT_DELETE) *p++ = 'E';
|
|
if (rights & NCP_RIGHT_MODIFY) *p++ = 'M';
|
|
if (rights & NCP_RIGHT_SEARCH) *p++ = 'F';
|
|
if (rights & NCP_RIGHT_OWNER) *p++ = 'A';
|
|
*p = '\0';
|
|
}
|
|
|
|
static int grant_add_right_word(char *s, uint16 *rights)
|
|
{
|
|
if (tool_strsame(s, "ALL")) {
|
|
*rights = NCP_RIGHT_ALL_386;
|
|
return(0);
|
|
}
|
|
|
|
if (tool_strsame(s, "N") || tool_strsame(s, "NONE")) {
|
|
*rights = 0;
|
|
return(0);
|
|
}
|
|
|
|
if (tool_strsame(s, "S") || tool_strsame(s, "SUPERVISOR")) {
|
|
*rights |= NCP_RIGHT_SUPER;
|
|
return(0);
|
|
}
|
|
|
|
if (tool_strsame(s, "R") || tool_strsame(s, "READ")) {
|
|
*rights |= NCP_RIGHT_READ;
|
|
return(0);
|
|
}
|
|
|
|
if (tool_strsame(s, "W") || tool_strsame(s, "WRITE")) {
|
|
*rights |= NCP_RIGHT_WRITE;
|
|
return(0);
|
|
}
|
|
|
|
if (tool_strsame(s, "C") || tool_strsame(s, "CREATE")) {
|
|
*rights |= NCP_RIGHT_CREATE;
|
|
return(0);
|
|
}
|
|
|
|
if (tool_strsame(s, "E") || tool_strsame(s, "ERASE")) {
|
|
*rights |= NCP_RIGHT_DELETE;
|
|
return(0);
|
|
}
|
|
|
|
if (tool_strsame(s, "M") || tool_strsame(s, "MODIFY")) {
|
|
*rights |= NCP_RIGHT_MODIFY;
|
|
return(0);
|
|
}
|
|
|
|
if (tool_strsame(s, "F") || tool_strsame(s, "FILESCAN") ||
|
|
tool_strsame(s, "FILE") || tool_strsame(s, "SCAN")) {
|
|
*rights |= NCP_RIGHT_SEARCH;
|
|
return(0);
|
|
}
|
|
|
|
if (tool_strsame(s, "A") || tool_strsame(s, "ACCESS") ||
|
|
tool_strsame(s, "CONTROL") || tool_strsame(s, "ACCESSCONTROL")) {
|
|
*rights |= NCP_RIGHT_OWNER;
|
|
return(0);
|
|
}
|
|
|
|
return(-1);
|
|
}
|
|
|
|
static int grant_last_rc = 0;
|
|
|
|
static int grant_set_one(char *path, uint16 dhandle,
|
|
uint32 object_id, uint16 rights)
|
|
{
|
|
int rc;
|
|
|
|
rc = c32_ncp87_add_trustee_rights(path,
|
|
dhandle,
|
|
object_id,
|
|
rights,
|
|
0xffff,
|
|
NULL, NULL, NULL);
|
|
grant_last_rc = rc;
|
|
return(rc);
|
|
}
|
|
|
|
/*
|
|
* Apply the grant to PATH and every directory below it.
|
|
*
|
|
* This intentionally walks through the DOS redirector, not through another
|
|
* NCP search helper, so it works with the same mapped-drive view that the
|
|
* user passed to GRANT.
|
|
*/
|
|
static int grant_set_subdirs(char *path, uint16 dhandle,
|
|
uint32 object_id, uint16 rights)
|
|
{
|
|
struct find_t ff;
|
|
char pattern[260];
|
|
char child[260];
|
|
int rc = 0;
|
|
|
|
if (grant_set_one(path, dhandle, object_id, rights))
|
|
rc = 1;
|
|
|
|
tool_join_path(pattern, path, "*.*", sizeof(pattern));
|
|
|
|
if (_dos_findfirst(pattern, _A_SUBDIR, &ff) == 0) {
|
|
do {
|
|
if ((ff.attrib & _A_SUBDIR) && !tool_is_dot_dir(ff.name)) {
|
|
tool_join_path(child, path, ff.name, sizeof(child));
|
|
if (grant_set_subdirs(child, dhandle, object_id, rights))
|
|
rc = 1;
|
|
}
|
|
} while (_dos_findnext(&ff) == 0);
|
|
}
|
|
|
|
return(rc);
|
|
}
|
|
|
|
|
|
int func_grant(int argc, char *argv[], int mode)
|
|
{
|
|
uint16 rights = 0;
|
|
char *path = ".";
|
|
char *objname = NULL;
|
|
uint16 objtype = GRANT_BINDERY_USER;
|
|
uint8 connid = 0;
|
|
uint8 dhandle = 0;
|
|
uint8 namebuf[48];
|
|
uint32 object_id;
|
|
int recurse_subdirs = 0;
|
|
int i = 1;
|
|
int have_rights = 0;
|
|
int rc;
|
|
|
|
(void)mode;
|
|
|
|
if (argc < 2 || tool_is_help_arg(argv[1])) {
|
|
if (argc < 2)
|
|
grant_usage_error();
|
|
grant_usage();
|
|
return(argc < 2 ? 1 : 0);
|
|
}
|
|
|
|
/*
|
|
* GRANT rightslist* [FOR path] TO [USER|GROUP] name [options]
|
|
*/
|
|
while (i < argc) {
|
|
if (tool_strsame(argv[i], "FOR") || tool_strsame(argv[i], "TO"))
|
|
break;
|
|
|
|
if (tool_is_option(argv[i]))
|
|
break;
|
|
|
|
if (grant_add_right_word(argv[i], &rights)) {
|
|
grant_usage_error();
|
|
grant_usage();
|
|
return(1);
|
|
}
|
|
have_rights = 1;
|
|
i++;
|
|
}
|
|
|
|
if (!have_rights || i >= argc) {
|
|
grant_usage_error();
|
|
grant_usage();
|
|
return(1);
|
|
}
|
|
|
|
if (tool_strsame(argv[i], "FOR")) {
|
|
i++;
|
|
if (i >= argc) {
|
|
grant_usage_error();
|
|
grant_usage();
|
|
return(1);
|
|
}
|
|
path = argv[i++];
|
|
}
|
|
|
|
if (i >= argc || !tool_strsame(argv[i], "TO")) {
|
|
grant_usage_error();
|
|
grant_usage();
|
|
return(1);
|
|
}
|
|
i++;
|
|
|
|
if (i < argc && tool_strsame(argv[i], "USER")) {
|
|
objtype = GRANT_BINDERY_USER;
|
|
i++;
|
|
} else if (i < argc && tool_strsame(argv[i], "GROUP")) {
|
|
objtype = GRANT_BINDERY_GROUP;
|
|
i++;
|
|
}
|
|
|
|
if (i >= argc) {
|
|
grant_usage_error();
|
|
grant_usage();
|
|
return(1);
|
|
}
|
|
|
|
objname = argv[i++];
|
|
|
|
while (i < argc) {
|
|
if (!tool_is_option(argv[i])) {
|
|
grant_usage_error();
|
|
grant_usage();
|
|
return(1);
|
|
}
|
|
|
|
/*
|
|
* /FILES is harmless because the explicit path is passed to the
|
|
* NCP87 trustee-add call. /SUBDIRECTORIES recursively applies the
|
|
* same grant to all subdirectories below the given path.
|
|
*/
|
|
if (tool_strsame(argv[i], "/FILES") || tool_strsame(argv[i], "-FILES") ||
|
|
tool_strsame(argv[i], "/F") || tool_strsame(argv[i], "-F")) {
|
|
i++;
|
|
continue;
|
|
}
|
|
|
|
if (tool_strsame(argv[i], "/SUBDIRECTORIES") ||
|
|
tool_strsame(argv[i], "-SUBDIRECTORIES") ||
|
|
tool_strsame(argv[i], "/S") || tool_strsame(argv[i], "-S")) {
|
|
recurse_subdirs = 1;
|
|
i++;
|
|
continue;
|
|
}
|
|
|
|
grant_usage_error();
|
|
grant_usage();
|
|
return(1);
|
|
}
|
|
|
|
if (tool_current_dhandle(&connid, &dhandle)) {
|
|
fprintf(stdout, "Specified path not locatable.\n");
|
|
return(1);
|
|
}
|
|
|
|
strmaxcpy(namebuf, objname, sizeof(namebuf) - 1);
|
|
upstr(namebuf);
|
|
object_id = ncp_17_35(namebuf, objtype);
|
|
if (!object_id) {
|
|
fprintf(stdout, "Object not found.\n");
|
|
return(1);
|
|
}
|
|
|
|
if (recurse_subdirs)
|
|
rc = grant_set_subdirs(path, (uint16)dhandle, object_id, rights);
|
|
else
|
|
rc = grant_set_one(path, (uint16)dhandle, object_id, rights);
|
|
|
|
if (rc) {
|
|
fprintf(stdout, "Could not add trustee rights. rc=%d\n", grant_last_rc);
|
|
return(grant_last_rc ? grant_last_rc : 1);
|
|
}
|
|
|
|
{
|
|
char header[300];
|
|
char base[80];
|
|
char bracket[10];
|
|
|
|
tool_header_path(header, path, sizeof(header));
|
|
tool_basename(base, path, sizeof(base));
|
|
grant_rights_bracket(rights, bracket);
|
|
|
|
fprintf(stdout, "%s\n", header);
|
|
fprintf(stdout, "%-29.29sRights set to [%s]\n", base, bracket);
|
|
}
|
|
|
|
return(0);
|
|
}
|