Implement REVOKE and REMOVE for the Client32 DOS utilities. REVOKE now supports Novell-style syntax: REVOKE rightslist* [FOR path] FROM [USER|GROUP] name [options] and removes rights from explicit trustee assignments. It scans the trustee list first, updates the trustee rights mask, and deletes the trustee entry when no rights remain. REMOVE now supports Novell-style syntax: REMOVE [USER | GROUP] name [FROM path] [option] and deletes explicit trustee assignments for users or groups. Both tools support USER/GROUP lookup, /FILES, /SUBDIRS, /SUBDIRECTORIES, wildcard file targets, recursive directory handling, Novell-style help text and summary output. Missing trustee entries are reported with Novell-style "No trustee for the specified ..." messages. Add shared trustee helpers and Client32 NCP87 trustee scan/delete support. Also adjust GRANT ALL so it matches Novell behavior by not granting Supervisor implicitly; Supervisor must be granted explicitly.
302 lines
7.7 KiB
C
302 lines
7.7 KiB
C
/* revoke.c - Novell REVOKE-like DOS utility */
|
|
|
|
#include "net.h"
|
|
#include "c32ncp.h"
|
|
#include "trustee.h"
|
|
|
|
#ifndef _A_NORMAL
|
|
#define _A_NORMAL 0x00
|
|
#endif
|
|
|
|
static int revoke_last_rc = 0;
|
|
|
|
static void revoke_usage_error(void)
|
|
{
|
|
fprintf(stdout, "Command line arguments violate grammar defined for REVOKE.\n\n");
|
|
}
|
|
|
|
static void revoke_usage(void)
|
|
{
|
|
fprintf(stdout, "Usage: REVOKE rightslist* [FOR path] FROM [USER|GROUP] name [options]\n");
|
|
fprintf(stdout, "Options: /SubDirectories | /Files\n\n");
|
|
fprintf(stdout, "286 Rights:\t\t386 Rights:\n");
|
|
fprintf(stdout, "---------------\t\t--------------------\n");
|
|
fprintf(stdout, "ALL = All\t\tALL = All\n");
|
|
fprintf(stdout, "R = Read\t\tS = Supervisor\n");
|
|
fprintf(stdout, "W = Write\t\tR = Read\n");
|
|
fprintf(stdout, "O = Open\t\tW = Write\n");
|
|
fprintf(stdout, "C = Create\t\tC = Create\n");
|
|
fprintf(stdout, "D = Delete\t\tE = Erase\n");
|
|
fprintf(stdout, "P = Parental\t\tM = Modify\n");
|
|
fprintf(stdout, "S = Search\t\tF = File Scan\n");
|
|
fprintf(stdout, "M = Modify\t\tA = Access Control\n");
|
|
fprintf(stdout, "\n* Use abbreviations listed above, separated by spaces.\n");
|
|
}
|
|
|
|
static int revoke_one(char *path, uint16 dhandle, uint32 object_id,
|
|
uint16 revoke_mask, int forced_is_file)
|
|
{
|
|
uint16 old_rights = 0;
|
|
uint16 new_rights;
|
|
int is_dir;
|
|
int rc;
|
|
|
|
is_dir = forced_is_file ? 0 : trustee_path_is_dir(path);
|
|
|
|
rc = c32_ncp87_find_trustee_rights(path, dhandle, object_id, &old_rights,
|
|
NULL, NULL, NULL);
|
|
revoke_last_rc = rc;
|
|
if (rc) {
|
|
if (rc == 0xff)
|
|
fprintf(stdout, "No trustee for the specified %s.\n", is_dir ? "directory" : "file");
|
|
else
|
|
fprintf(stdout, "Error scanning trustee list.\n");
|
|
return(1);
|
|
}
|
|
|
|
new_rights = (uint16)(old_rights & ~revoke_mask);
|
|
|
|
if (new_rights == 0) {
|
|
rc = c32_ncp87_delete_trustee_rights(path, dhandle, object_id,
|
|
NULL, NULL, NULL);
|
|
revoke_last_rc = rc;
|
|
if (rc) {
|
|
fprintf(stdout, "Error deleting trustee.\n");
|
|
return(1);
|
|
}
|
|
} else {
|
|
rc = c32_ncp87_add_trustee_rights(path, dhandle, object_id, new_rights,
|
|
0xffff, NULL, NULL, NULL);
|
|
revoke_last_rc = rc;
|
|
if (rc) {
|
|
fprintf(stdout, "Fatal error revoking access rights.\n");
|
|
return(1);
|
|
}
|
|
}
|
|
|
|
{
|
|
char header[300];
|
|
char bracket[10];
|
|
trustee_header_path(header, path, sizeof(header));
|
|
trustee_rights_bracket(new_rights, bracket);
|
|
fprintf(stdout, "%s\n\n", header);
|
|
fprintf(stdout, "Trustee's access rights set to [%s]\n", bracket);
|
|
}
|
|
|
|
return(0);
|
|
}
|
|
|
|
static int revoke_subdirs(char *path, uint16 dhandle, uint32 object_id,
|
|
uint16 revoke_mask, int *count)
|
|
{
|
|
struct find_t ff;
|
|
char pattern[260];
|
|
char child[260];
|
|
int rc = 0;
|
|
|
|
if (revoke_one(path, dhandle, object_id, revoke_mask, 0) == 0)
|
|
(*count)++;
|
|
else
|
|
rc = 1;
|
|
|
|
trustee_join_path(pattern, path, "*.*", sizeof(pattern));
|
|
|
|
if (_dos_findfirst(pattern, _A_SUBDIR, &ff) == 0) {
|
|
do {
|
|
if ((ff.attrib & _A_SUBDIR) && !trustee_is_dot_dir(ff.name)) {
|
|
trustee_join_path(child, path, ff.name, sizeof(child));
|
|
if (revoke_subdirs(child, dhandle, object_id, revoke_mask, count))
|
|
rc = 1;
|
|
}
|
|
} while (_dos_findnext(&ff) == 0);
|
|
}
|
|
|
|
return(rc);
|
|
}
|
|
|
|
static int revoke_files(char *path, uint16 dhandle, uint32 object_id,
|
|
uint16 revoke_mask, int *count)
|
|
{
|
|
struct find_t ff;
|
|
char dir[260];
|
|
char pat[80];
|
|
char spec[260];
|
|
char target[260];
|
|
int rc = 0;
|
|
|
|
if (trustee_path_is_dir(path)) {
|
|
strmaxcpy(dir, path, sizeof(dir) - 1);
|
|
strmaxcpy(pat, "*.*", sizeof(pat) - 1);
|
|
} else if (trustee_path_has_wildcards(path)) {
|
|
trustee_parent_pattern(dir, pat, path, sizeof(dir), sizeof(pat));
|
|
} else {
|
|
if (revoke_one(path, dhandle, object_id, revoke_mask, 1) == 0)
|
|
(*count)++;
|
|
else
|
|
rc = 1;
|
|
return(rc);
|
|
}
|
|
|
|
trustee_join_path(spec, dir, pat, sizeof(spec));
|
|
if (_dos_findfirst(spec, _A_NORMAL | _A_HIDDEN | _A_SYSTEM | _A_ARCH, &ff) == 0) {
|
|
do {
|
|
if (!(ff.attrib & _A_SUBDIR)) {
|
|
trustee_join_path(target, dir, ff.name, sizeof(target));
|
|
if (revoke_one(target, dhandle, object_id, revoke_mask, 1) == 0)
|
|
(*count)++;
|
|
else
|
|
rc = 1;
|
|
}
|
|
} while (_dos_findnext(&ff) == 0);
|
|
}
|
|
|
|
return(rc);
|
|
}
|
|
|
|
int func_revoke(int argc, char *argv[], int mode)
|
|
{
|
|
uint16 rights = 0;
|
|
char *path = ".";
|
|
char *objname = NULL;
|
|
char objprint[48];
|
|
uint16 objtype = TRUSTEE_BINDERY_USER;
|
|
int objtype_given = 0;
|
|
uint8 connid = 0;
|
|
uint8 dhandle = 0;
|
|
uint32 object_id;
|
|
int use_subdirs = 0;
|
|
int use_files = 0;
|
|
int count = 0;
|
|
int i = 1;
|
|
int have_rights = 0;
|
|
int rc;
|
|
|
|
(void)mode;
|
|
|
|
if (argc < 2 || trustee_is_help(argv[1])) {
|
|
if (argc < 2)
|
|
revoke_usage_error();
|
|
revoke_usage();
|
|
return(argc < 2 ? 1 : 0);
|
|
}
|
|
|
|
while (i < argc) {
|
|
if (trustee_same(argv[i], "FOR") || trustee_same(argv[i], "FROM"))
|
|
break;
|
|
if (trustee_is_option(argv[i]))
|
|
break;
|
|
if (trustee_parse_right_word(argv[i], &rights)) {
|
|
fprintf(stdout, "Invalid right specified.\n");
|
|
revoke_usage();
|
|
return(1);
|
|
}
|
|
have_rights = 1;
|
|
i++;
|
|
}
|
|
|
|
if (!have_rights || i >= argc) {
|
|
revoke_usage_error();
|
|
revoke_usage();
|
|
return(1);
|
|
}
|
|
|
|
if (trustee_same(argv[i], "FOR")) {
|
|
i++;
|
|
if (i >= argc) {
|
|
revoke_usage_error();
|
|
revoke_usage();
|
|
return(1);
|
|
}
|
|
path = argv[i++];
|
|
}
|
|
|
|
if (i >= argc || !trustee_same(argv[i], "FROM")) {
|
|
revoke_usage_error();
|
|
revoke_usage();
|
|
return(1);
|
|
}
|
|
i++;
|
|
|
|
if (i < argc && trustee_same(argv[i], "USER")) {
|
|
objtype = TRUSTEE_BINDERY_USER;
|
|
objtype_given = 1;
|
|
i++;
|
|
} else if (i < argc && trustee_same(argv[i], "GROUP")) {
|
|
objtype = TRUSTEE_BINDERY_GROUP;
|
|
objtype_given = 1;
|
|
i++;
|
|
}
|
|
|
|
if (i >= argc) {
|
|
revoke_usage_error();
|
|
revoke_usage();
|
|
return(1);
|
|
}
|
|
|
|
objname = argv[i++];
|
|
|
|
while (i < argc) {
|
|
if (!trustee_is_option(argv[i])) {
|
|
revoke_usage_error();
|
|
revoke_usage();
|
|
return(1);
|
|
}
|
|
|
|
if (trustee_is_files_option(argv[i])) {
|
|
use_files = 1;
|
|
i++;
|
|
continue;
|
|
}
|
|
|
|
if (trustee_is_subdirs_option(argv[i])) {
|
|
use_subdirs = 1;
|
|
i++;
|
|
continue;
|
|
}
|
|
|
|
revoke_usage_error();
|
|
revoke_usage();
|
|
return(1);
|
|
}
|
|
|
|
if (use_files && use_subdirs) {
|
|
fprintf(stdout, "Revoke cannot do both directories and files in a single pass.\n");
|
|
return(1);
|
|
}
|
|
|
|
if (trustee_current_dhandle(&connid, &dhandle)) {
|
|
fprintf(stdout, "Error: Drive not mapped to Network.\n");
|
|
return(1);
|
|
}
|
|
|
|
object_id = trustee_lookup_object(objname, &objtype, objtype_given);
|
|
if (!object_id) {
|
|
if (objtype_given && objtype == TRUSTEE_BINDERY_GROUP)
|
|
fprintf(stdout, "Group \"%s\" not found.\n", objname);
|
|
else if (objtype_given)
|
|
fprintf(stdout, "User \"%s\" not found.\n", objname);
|
|
else
|
|
fprintf(stdout, "User or group \"%s\" not found.\n", objname);
|
|
return(1);
|
|
}
|
|
|
|
trustee_upcopy(objprint, objname, sizeof(objprint));
|
|
|
|
if (use_subdirs)
|
|
rc = revoke_subdirs(path, (uint16)dhandle, object_id, rights, &count);
|
|
else if (use_files)
|
|
rc = revoke_files(path, (uint16)dhandle, object_id, rights, &count);
|
|
else {
|
|
rc = revoke_one(path, (uint16)dhandle, object_id, rights, 0);
|
|
if (!rc)
|
|
count = 1;
|
|
}
|
|
|
|
if (use_subdirs || (!use_files && !rc))
|
|
fprintf(stdout, "Rights for %d directories were changed for %s.\n", count, objprint);
|
|
else if (use_files)
|
|
fprintf(stdout, "Rights for %d files were changed for %s.\n", count, objprint);
|
|
|
|
return(rc ? (revoke_last_rc ? revoke_last_rc : 1) : 0);
|
|
}
|